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 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:612
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().

◆ create_seq_hashtable()

static void create_seq_hashtable ( void  )
static

Definition at line 1111 of file sequence.c.

1112 {
1113  HASHCTL ctl;
1114 
1115  ctl.keysize = sizeof(Oid);
1116  ctl.entrysize = sizeof(SeqTableData);
1117 
1118  seqhashtab = hash_create("Sequence values", 16, &ctl,
1119  HASH_ELEM | HASH_BLOBS);
1120 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#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 864 of file sequence.c.

865 {
866  Oid relid = PG_GETARG_OID(0);
867  int64 result;
868  SeqTable elm;
869  Relation seqrel;
870 
871  /* open and lock sequence */
872  init_sequence(relid, &elm, &seqrel);
873 
874  if (pg_class_aclcheck(elm->relid, GetUserId(),
876  ereport(ERROR,
877  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
878  errmsg("permission denied for sequence %s",
879  RelationGetRelationName(seqrel))));
880 
881  if (!elm->last_valid)
882  ereport(ERROR,
883  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
884  errmsg("currval of sequence \"%s\" is not yet defined in this session",
885  RelationGetRelationName(seqrel))));
886 
887  result = elm->last;
888 
889  relation_close(seqrel, NoLock);
890 
891  PG_RETURN_INT64(result);
892 }
@ ACLCHECK_OK
Definition: acl.h:182
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:5007
int errcode(int sqlerrcode)
Definition: elog.c:693
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
Oid GetUserId(void)
Definition: miscinit.c:492
#define ACL_USAGE
Definition: parsenodes.h:90
#define ACL_SELECT
Definition: parsenodes.h:83
#define RelationGetRelationName(relation)
Definition: rel.h:522
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;
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  {
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
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:514
#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
bool if_not_exists
Definition: parsenodes.h:3010
List * options
Definition: parsenodes.h:3007
RangeVar * sequence
Definition: parsenodes.h:3006
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().

◆ do_setval()

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

Definition at line 943 of file sequence.c.

944 {
945  SeqTable elm;
946  Relation seqrel;
947  Buffer buf;
948  HeapTupleData seqdatatuple;
950  HeapTuple pgstuple;
951  Form_pg_sequence pgsform;
952  int64 maxv,
953  minv;
954 
955  /* open and lock sequence */
956  init_sequence(relid, &elm, &seqrel);
957 
959  ereport(ERROR,
960  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
961  errmsg("permission denied for sequence %s",
962  RelationGetRelationName(seqrel))));
963 
964  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
965  if (!HeapTupleIsValid(pgstuple))
966  elog(ERROR, "cache lookup failed for sequence %u", relid);
967  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
968  maxv = pgsform->seqmax;
969  minv = pgsform->seqmin;
970  ReleaseSysCache(pgstuple);
971 
972  /* read-only transactions may only modify temp sequences */
973  if (!seqrel->rd_islocaltemp)
974  PreventCommandIfReadOnly("setval()");
975 
976  /*
977  * Forbid this during parallel operation because, to make it work, the
978  * cooperating backends would need to share the backend-local cached
979  * sequence information. Currently, we don't support that.
980  */
981  PreventCommandIfParallelMode("setval()");
982 
983  /* lock page' buffer and read tuple */
984  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
985 
986  if ((next < minv) || (next > maxv))
987  ereport(ERROR,
988  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
989  errmsg("setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)",
990  (long long) next, RelationGetRelationName(seqrel),
991  (long long) minv, (long long) maxv)));
992 
993  /* Set the currval() state only if iscalled = true */
994  if (iscalled)
995  {
996  elm->last = next; /* last returned number */
997  elm->last_valid = true;
998  }
999 
1000  /* In any case, forget any future cached numbers */
1001  elm->cached = elm->last;
1002 
1003  /* check the comment above nextval_internal()'s equivalent call. */
1004  if (RelationNeedsWAL(seqrel))
1006 
1007  /* ready to change the on-disk (or really, in-buffer) tuple */
1009 
1010  seq->last_value = next; /* last fetched number */
1011  seq->is_called = iscalled;
1012  seq->log_cnt = 0;
1013 
1015 
1016  /* XLOG stuff */
1017  if (RelationNeedsWAL(seqrel))
1018  {
1019  xl_seq_rec xlrec;
1020  XLogRecPtr recptr;
1021  Page page = BufferGetPage(buf);
1022 
1023  XLogBeginInsert();
1025 
1026  xlrec.node = seqrel->rd_node;
1027  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
1028  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
1029 
1030  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
1031 
1032  PageSetLSN(page, recptr);
1033  }
1034 
1035  END_CRIT_SECTION();
1036 
1038 
1039  relation_close(seqrel, NoLock);
1040 }
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 START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
#define ACL_UPDATE
Definition: parsenodes.h:84
#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
RelFileNode node
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
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, 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, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, xl_seq_rec::node, NoLock, ObjectIdGetDatum, 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(), 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 363 of file sequence.c.

364 {
365  Buffer buf;
366  Page page;
367  sequence_magic *sm;
368  OffsetNumber offnum;
369 
370  /* Initialize first page of relation with special magic number */
371 
372  buf = ReadBufferExtended(rel, forkNum, P_NEW, RBM_NORMAL, NULL);
374 
375  page = BufferGetPage(buf);
376 
377  PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
378  sm = (sequence_magic *) PageGetSpecialPointer(page);
379  sm->magic = SEQ_MAGIC;
380 
381  /* Now insert sequence tuple */
382 
384 
385  /*
386  * Since VACUUM does not process sequences, we have to force the tuple to
387  * have xmin = FrozenTransactionId now. Otherwise it would become
388  * invisible to SELECTs after 2G transactions. It is okay to do this
389  * because if the current transaction aborts, no other xact will ever
390  * examine the sequence tuple anyway.
391  */
398 
399  /* check the comment above nextval_internal()'s equivalent call. */
400  if (RelationNeedsWAL(rel))
402 
404 
406 
407  offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
408  InvalidOffsetNumber, false, false);
409  if (offnum != FirstOffsetNumber)
410  elog(ERROR, "failed to add sequence tuple to page");
411 
412  /* XLOG stuff */
413  if (RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM)
414  {
415  xl_seq_rec xlrec;
416  XLogRecPtr recptr;
417 
418  XLogBeginInsert();
420 
421  xlrec.node = rel->rd_node;
422 
423  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
424  XLogRegisterData((char *) tuple->t_data, tuple->t_len);
425 
426  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
427 
428  PageSetLSN(page, recptr);
429  }
430 
432 
434 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2755
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4156
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:749
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
#define P_NEW
Definition: bufmgr.h:91
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
@ RBM_NORMAL
Definition: bufmgr.h:39
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
#define FirstCommandId
Definition: c.h:603
#define HeapTupleHeaderSetXminFrozen(tup)
Definition: htup_details.h:347
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:314
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:375
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:392
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
Pointer Item
Definition: item.h:17
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127
#define InvalidOffsetNumber
Definition: off.h:26
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
@ INIT_FORKNUM
Definition: relpath.h:46
#define SEQ_MAGIC
Definition: sequence.c:62
ItemPointerData t_ctid
Definition: htup_details.h:160
uint32 magic
Definition: sequence.c:66
#define FrozenTransactionId
Definition: transam.h:33

References Assert(), buf, BUFFER_LOCK_EXCLUSIVE, BufferGetBlockNumber(), BufferGetPage, BufferGetPageSize, elog, END_CRIT_SECTION, ERROR, FirstCommandId, FirstOffsetNumber, FrozenTransactionId, GetTopTransactionId(), HEAP_XMAX_INVALID, HeapTupleHeaderSetCmin, HeapTupleHeaderSetXmax, HeapTupleHeaderSetXmin, HeapTupleHeaderSetXminFrozen, INIT_FORKNUM, InvalidOffsetNumber, InvalidTransactionId, ItemPointerSet, LockBuffer(), sequence_magic::magic, MarkBufferDirty(), xl_seq_rec::node, P_NEW, PageAddItem, PageGetSpecialPointer, PageInit(), PageSetLSN, RBM_NORMAL, RelationData::rd_node, ReadBufferExtended(), 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 342 of file sequence.c.

343 {
345 
346  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
347  {
348  SMgrRelation srel;
349 
350  srel = smgropen(rel->rd_node, InvalidBackendId);
351  smgrcreate(srel, INIT_FORKNUM, false);
355  smgrclose(srel);
356  }
357 }
#define InvalidBackendId
Definition: backendid.h:23
void FlushRelationBuffers(Relation rel)
Definition: bufmgr.c:3508
@ MAIN_FORKNUM
Definition: relpath.h:43
static void fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
Definition: sequence.c:363
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:369
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:146
void log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:185

References fill_seq_fork_with_data(), FlushRelationBuffers(), INIT_FORKNUM, InvalidBackendId, log_smgrcreate(), MAIN_FORKNUM, RelationData::rd_node, 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 1260 of file sequence.c.

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

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

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

References SeqTableData::cached, create_seq_hashtable(), ereport, errcode(), errmsg(), ERROR, SeqTableData::filenode, HASH_ENTER, hash_search(), InvalidLocalTransactionId, InvalidOid, 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 895 of file sequence.c.

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

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

1084 {
1085  LocalTransactionId thislxid = MyProc->lxid;
1086 
1087  /* Get the lock if not already held in this xact */
1088  if (seq->lxid != thislxid)
1089  {
1090  ResourceOwner currentOwner;
1091 
1092  currentOwner = CurrentResourceOwner;
1094 
1096 
1097  CurrentResourceOwner = currentOwner;
1098 
1099  /* Flag that we have a lock in the current xact */
1100  seq->lxid = thislxid;
1101  }
1102 
1103  /* We now know we have the lock, and can safely open the rel */
1104  return relation_open(seq->relid, NoLock);
1105 }
uint32 LocalTransactionId
Definition: c.h:589
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:148
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
PGPROC * MyProc
Definition: proc.c:68
LocalTransactionId lxid
Definition: proc.h:181

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 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
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 }
#define PageGetLSN(page)
Definition: bufpage.h:365
#define SEQ_LOG_VALS
Definition: sequence.c:57
int64 increment
Definition: sequence.c:84
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:5865

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

◆ nextval_oid()

Datum nextval_oid ( PG_FUNCTION_ARGS  )

Definition at line 613 of file sequence.c.

614 {
615  Oid relid = PG_GETARG_OID(0);
616 
617  PG_RETURN_INT64(nextval_internal(relid, true));
618 }

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

1801 {
1802  Oid relid = PG_GETARG_OID(0);
1803  SeqTable elm;
1804  Relation seqrel;
1805  Buffer buf;
1806  HeapTupleData seqtuple;
1808  bool is_called;
1809  int64 result;
1810 
1811  /* open and lock sequence */
1812  init_sequence(relid, &elm, &seqrel);
1813 
1815  ereport(ERROR,
1816  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1817  errmsg("permission denied for sequence %s",
1818  RelationGetRelationName(seqrel))));
1819 
1820  seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1821 
1822  is_called = seq->is_called;
1823  result = seq->last_value;
1824 
1826  relation_close(seqrel, NoLock);
1827 
1828  if (is_called)
1829  PG_RETURN_INT64(result);
1830  else
1831  PG_RETURN_NULL();
1832 }
#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 1741 of file sequence.c.

1742 {
1743  Oid relid = PG_GETARG_OID(0);
1744  TupleDesc tupdesc;
1745  Datum values[7];
1746  bool isnull[7];
1747  HeapTuple pgstuple;
1748  Form_pg_sequence pgsform;
1749 
1751  ereport(ERROR,
1752  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1753  errmsg("permission denied for sequence %s",
1754  get_rel_name(relid))));
1755 
1756  tupdesc = CreateTemplateTupleDesc(7);
1757  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
1758  INT8OID, -1, 0);
1759  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
1760  INT8OID, -1, 0);
1761  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
1762  INT8OID, -1, 0);
1763  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
1764  INT8OID, -1, 0);
1765  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
1766  BOOLOID, -1, 0);
1767  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size",
1768  INT8OID, -1, 0);
1769  TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type",
1770  OIDOID, -1, 0);
1771 
1772  BlessTupleDesc(tupdesc);
1773 
1774  memset(isnull, 0, sizeof(isnull));
1775 
1776  pgstuple = SearchSysCache1(SEQRELID, relid);
1777  if (!HeapTupleIsValid(pgstuple))
1778  elog(ERROR, "cache lookup failed for sequence %u", relid);
1779  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1780 
1781  values[0] = Int64GetDatum(pgsform->seqstart);
1782  values[1] = Int64GetDatum(pgsform->seqmin);
1783  values[2] = Int64GetDatum(pgsform->seqmax);
1784  values[3] = Int64GetDatum(pgsform->seqincrement);
1785  values[4] = BoolGetDatum(pgsform->seqcycle);
1786  values[5] = Int64GetDatum(pgsform->seqcache);
1787  values[6] = ObjectIdGetDatum(pgsform->seqtypid);
1788 
1789  ReleaseSysCache(pgstuple);
1790 
1791  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
1792 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2071
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:220
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1909
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583

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

◆ process_owned_by()

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

Definition at line 1593 of file sequence.c.

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

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(), list_length(), list_truncate(), 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 1194 of file sequence.c.

1195 {
1196  Page page;
1197  ItemId lp;
1198  sequence_magic *sm;
1200 
1201  *buf = ReadBuffer(rel, 0);
1203 
1204  page = BufferGetPage(*buf);
1205  sm = (sequence_magic *) PageGetSpecialPointer(page);
1206 
1207  if (sm->magic != SEQ_MAGIC)
1208  elog(ERROR, "bad magic number in sequence \"%s\": %08X",
1209  RelationGetRelationName(rel), sm->magic);
1210 
1211  lp = PageGetItemId(page, FirstOffsetNumber);
1212  Assert(ItemIdIsNormal(lp));
1213 
1214  /* Note we currently only bother to set these two fields of *seqdatatuple */
1215  seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1216  seqdatatuple->t_len = ItemIdGetLength(lp);
1217 
1218  /*
1219  * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1220  * a sequence, which would leave a non-frozen XID in the sequence tuple's
1221  * xmax, which eventually leads to clog access failures or worse. If we
1222  * see this has happened, clean up after it. We treat this like a hint
1223  * bit update, ie, don't bother to WAL-log it, since we can certainly do
1224  * this again if the update gets lost.
1225  */
1226  Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
1228  {
1230  seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
1231  seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
1232  MarkBufferDirtyHint(*buf, true);
1233  }
1234 
1235  seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
1236 
1237  return seq;
1238 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3985
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:702
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:234
#define PageGetItem(page, itemId)
Definition: bufpage.h:339
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:370
#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 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

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

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 }
unsigned char uint8
Definition: c.h:439
size_t Size
Definition: c.h:540
#define PANIC
Definition: elog.h:36
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
struct xl_seq_rec xl_seq_rec
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:414
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:408
#define XLogRecGetData(decoder)
Definition: xlogreader.h:413
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
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().

◆ setval3_oid()

Datum setval3_oid ( PG_FUNCTION_ARGS  )

Definition at line 1062 of file sequence.c.

1063 {
1064  Oid relid = PG_GETARG_OID(0);
1065  int64 next = PG_GETARG_INT64(1);
1066  bool iscalled = PG_GETARG_BOOL(2);
1067 
1068  do_setval(relid, next, iscalled);
1069 
1071 }
#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:943

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

1048 {
1049  Oid relid = PG_GETARG_OID(0);
1050  int64 next = PG_GETARG_INT64(1);
1051 
1052  do_setval(relid, next, true);
1053 
1055 }

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