PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
sequence.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/htup_details.h"
#include "access/multixact.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 "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 int64 nextval_internal (Oid relid)
 
static Relation open_share_lock (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 isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, List **owned_by)
 
static void do_setval (Oid relid, int64 next, bool iscalled)
 
static void process_owned_by (Relation seqrel, List *owned_by)
 
ObjectAddress DefineSequence (ParseState *pstate, CreateSeqStmt *seq)
 
void ResetSequence (Oid seq_relid)
 
ObjectAddress AlterSequence (ParseState *pstate, AlterSeqStmt *stmt)
 
void DeleteSequenceTuple (Oid relid)
 
Datum nextval (PG_FUNCTION_ARGS)
 
Datum nextval_oid (PG_FUNCTION_ARGS)
 
Datum currval_oid (PG_FUNCTION_ARGS)
 
Datum lastval (PG_FUNCTION_ARGS)
 
Datum setval_oid (PG_FUNCTION_ARGS)
 
Datum setval3_oid (PG_FUNCTION_ARGS)
 
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

#define SEQ_LOG_VALS   32

Definition at line 54 of file sequence.c.

Referenced by nextval_internal().

#define SEQ_MAGIC   0x1717

Definition at line 59 of file sequence.c.

Referenced by fill_seq_with_data(), read_seq_tuple(), and seq_redo().

Typedef Documentation

Definition at line 85 of file sequence.c.

Function Documentation

ObjectAddress AlterSequence ( ParseState pstate,
AlterSeqStmt stmt 
)

Definition at line 410 of file sequence.c.

References AccessShareLock, ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, buf, BufferGetPage, SeqTableData::cached, CatalogTupleUpdate(), elog, END_CRIT_SECTION, ereport, errmsg(), ERROR, GETSTRUCT, GetTopTransactionId(), GetUserId(), heap_close, heap_open(), HeapTupleIsValid, init_params(), init_sequence(), InvalidObjectAddress, InvalidOid, InvokeObjectPostAlterHook, SeqTableData::last, MarkBufferDirty(), AlterSeqStmt::missing_ok, xl_seq_rec::node, NoLock, NOTICE, ObjectAddressSet, ObjectIdGetDatum, AlterSeqStmt::options, PageSetLSN, pg_class_ownercheck(), process_owned_by(), RangeVarGetRelid, RelationData::rd_node, read_seq_tuple(), REGBUF_WILL_INIT, relation_close(), RelationNeedsWAL, RelationRelationId, RangeVar::relname, RowExclusiveLock, SearchSysCacheCopy1, SEQRELID, AlterSeqStmt::sequence, SequenceRelationId, START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by ProcessUtilitySlow().

411 {
412  Oid relid;
413  SeqTable elm;
414  Relation seqrel;
415  Buffer buf;
416  HeapTupleData seqdatatuple;
417  Form_pg_sequence seqform;
418  Form_pg_sequence_data seqdata;
419  FormData_pg_sequence_data newseqdata;
420  List *owned_by;
421  ObjectAddress address;
422  Relation rel;
423  HeapTuple tuple;
424 
425  /* Open and lock sequence. */
426  relid = RangeVarGetRelid(stmt->sequence, AccessShareLock, stmt->missing_ok);
427  if (relid == InvalidOid)
428  {
429  ereport(NOTICE,
430  (errmsg("relation \"%s\" does not exist, skipping",
431  stmt->sequence->relname)));
432  return InvalidObjectAddress;
433  }
434 
435  init_sequence(relid, &elm, &seqrel);
436 
437  /* allow ALTER to sequence owner only */
438  if (!pg_class_ownercheck(relid, GetUserId()))
440  stmt->sequence->relname);
441 
442  /* lock page' buffer and read tuple into new sequence structure */
443  seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
444 
445  /* Copy old values of options into workspace */
446  memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
447 
450  ObjectIdGetDatum(relid));
451  if (!HeapTupleIsValid(tuple))
452  elog(ERROR, "cache lookup failed for sequence %u",
453  relid);
454 
455  seqform = (Form_pg_sequence) GETSTRUCT(tuple);
456 
457  /* Check and set new values */
458  init_params(pstate, stmt->options, false, seqform, &newseqdata, &owned_by);
459 
460  /* Clear local cache so that we don't think we have cached numbers */
461  /* Note that we do not change the currval() state */
462  elm->cached = elm->last;
463 
464  /* check the comment above nextval_internal()'s equivalent call. */
465  if (RelationNeedsWAL(seqrel))
467 
468  /* Now okay to update the on-disk tuple */
470 
471  memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
472 
473  MarkBufferDirty(buf);
474 
475  /* XLOG stuff */
476  if (RelationNeedsWAL(seqrel))
477  {
478  xl_seq_rec xlrec;
479  XLogRecPtr recptr;
480  Page page = BufferGetPage(buf);
481 
482  XLogBeginInsert();
484 
485  xlrec.node = seqrel->rd_node;
486  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
487 
488  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
489 
490  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
491 
492  PageSetLSN(page, recptr);
493  }
494 
496 
497  UnlockReleaseBuffer(buf);
498 
499  /* process OWNED BY if given */
500  if (owned_by)
501  process_owned_by(seqrel, owned_by);
502 
504 
505  ObjectAddressSet(address, RelationRelationId, relid);
506 
507  relation_close(seqrel, NoLock);
508 
509  CatalogTupleUpdate(rel, &tuple->t_self, tuple);
511 
512  return address;
513 }
int64 cached
Definition: sequence.c:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:283
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
#define RelationRelationId
Definition: pg_class.h:29
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
#define AccessShareLock
Definition: lockdefs.h:36
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
#define SequenceRelationId
Definition: pg_sequence.h:6
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
#define heap_close(r, l)
Definition: heapam.h:97
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
RelFileNode node
Definition: sequence.h:50
unsigned int Oid
Definition: postgres_ext.h:31
static void process_owned_by(Relation seqrel, List *owned_by)
Definition: sequence.c:1568
List * options
Definition: parsenodes.h:2367
HeapTupleHeader t_data
Definition: htup.h:67
char * relname
Definition: primnodes.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:65
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
int64 last
Definition: sequence.c:78
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1167
static void init_params(ParseState *pstate, List *options, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, List **owned_by)
Definition: sequence.c:1222
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
RangeVar * sequence
Definition: parsenodes.h:2366
#define NOTICE
Definition: elog.h:37
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
uint64 XLogRecPtr
Definition: xlogdefs.h:21
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4521
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define RelationNeedsWAL(relation)
Definition: rel.h:502
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:158
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
Definition: pg_list.h:45
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
static void create_seq_hashtable ( void  )
static

Definition at line 1083 of file sequence.c.

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

Referenced by init_sequence().

1084 {
1085  HASHCTL ctl;
1086 
1087  memset(&ctl, 0, sizeof(ctl));
1088  ctl.keysize = sizeof(Oid);
1089  ctl.entrysize = sizeof(SeqTableData);
1090 
1091  seqhashtab = hash_create("Sequence values", 16, &ctl,
1092  HASH_ELEM | HASH_BLOBS);
1093 }
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
struct SeqTableData SeqTableData
unsigned int Oid
Definition: postgres_ext.h:31
static HTAB * seqhashtab
Definition: sequence.c:87
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
Datum currval_oid ( PG_FUNCTION_ARGS  )

Definition at line 819 of file sequence.c.

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.

820 {
821  Oid relid = PG_GETARG_OID(0);
822  int64 result;
823  SeqTable elm;
824  Relation seqrel;
825 
826  /* open and AccessShareLock sequence */
827  init_sequence(relid, &elm, &seqrel);
828 
829  if (pg_class_aclcheck(elm->relid, GetUserId(),
831  ereport(ERROR,
832  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
833  errmsg("permission denied for sequence %s",
834  RelationGetRelationName(seqrel))));
835 
836  if (!elm->last_valid)
837  ereport(ERROR,
838  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
839  errmsg("currval of sequence \"%s\" is not yet defined in this session",
840  RelationGetRelationName(seqrel))));
841 
842  result = elm->last;
843 
844  relation_close(seqrel, NoLock);
845 
846  PG_RETURN_INT64(result);
847 }
Oid GetUserId(void)
Definition: miscinit.c:283
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define RelationGetRelationName(relation)
Definition: rel.h:433
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:73
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_SELECT
Definition: parsenodes.h:66
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
int errmsg(const char *fmt,...)
Definition: elog.c:797
ObjectAddress DefineSequence ( ParseState pstate,
CreateSeqStmt seq 
)

Definition at line 114 of file sequence.c.

References AccessExclusiveLock, Anum_pg_sequence_seqcache, Anum_pg_sequence_seqcycle, Anum_pg_sequence_seqincrement, Anum_pg_sequence_seqmax, Anum_pg_sequence_seqmin, Anum_pg_sequence_seqrelid, Anum_pg_sequence_seqstart, Anum_pg_sequence_seqtypid, Assert, BoolGetDatum, BOOLOID, CatalogTupleInsert(), ColumnDef::collClause, ColumnDef::collOid, ColumnDef::colname, ColumnDef::constraints, CreateStmt::constraints, ColumnDef::cooked_default, DefineRelation(), ereport, errcode(), errmsg(), ERROR, fill_seq_with_data(), FormData_pg_sequence, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), i, CreateStmt::if_not_exists, CreateSeqStmt::if_not_exists, ColumnDef::inhcount, CreateStmt::inhRelations, init_params(), Int64GetDatum(), Int64GetDatumFast, INT8OID, InvalidObjectAddress, InvalidOid, ColumnDef::is_from_type, ColumnDef::is_local, ColumnDef::is_not_null, lappend(), FormData_pg_sequence_data::last_value, ColumnDef::location, makeNode, makeTypeNameFromOid(), Natts_pg_sequence, NIL, NoLock, NOTICE, NULL, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, CreateSeqStmt::options, CreateSeqStmt::ownerId, process_owned_by(), RangeVarGetAndCheckCreationNamespace(), ColumnDef::raw_default, CreateStmt::relation, RelationGetDescr, RELKIND_SEQUENCE, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_UNLOGGED, RowExclusiveLock, SEQ_COL_CALLED, SEQ_COL_FIRSTCOL, SEQ_COL_LASTCOL, SEQ_COL_LASTVAL, SEQ_COL_LOG, CreateSeqStmt::sequence, SequenceRelationId, ColumnDef::storage, CreateStmt::tableElts, CreateStmt::tablespacename, ColumnDef::typeName, and value.

Referenced by ProcessUtilitySlow().

115 {
116  FormData_pg_sequence seqform;
117  FormData_pg_sequence_data seqdataform;
118  List *owned_by;
119  CreateStmt *stmt = makeNode(CreateStmt);
120  Oid seqoid;
121  ObjectAddress address;
122  Relation rel;
123  HeapTuple tuple;
124  TupleDesc tupDesc;
126  bool null[SEQ_COL_LASTCOL];
127  Datum pgs_values[Natts_pg_sequence];
128  bool pgs_nulls[Natts_pg_sequence];
129  int i;
130 
131  /* Unlogged sequences are not implemented -- not clear if useful. */
133  ereport(ERROR,
134  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
135  errmsg("unlogged sequences are not supported")));
136 
137  /*
138  * If if_not_exists was given and a relation with the same name already
139  * exists, bail out. (Note: we needn't check this when not if_not_exists,
140  * because DefineRelation will complain anyway.)
141  */
142  if (seq->if_not_exists)
143  {
145  if (OidIsValid(seqoid))
146  {
147  ereport(NOTICE,
148  (errcode(ERRCODE_DUPLICATE_TABLE),
149  errmsg("relation \"%s\" already exists, skipping",
150  seq->sequence->relname)));
151  return InvalidObjectAddress;
152  }
153  }
154 
155  /* Check and set all option values */
156  init_params(pstate, seq->options, true, &seqform, &seqdataform, &owned_by);
157 
158  /*
159  * Create relation (and fill value[] and null[] for the tuple)
160  */
161  stmt->tableElts = NIL;
162  for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
163  {
164  ColumnDef *coldef = makeNode(ColumnDef);
165 
166  coldef->inhcount = 0;
167  coldef->is_local = true;
168  coldef->is_not_null = true;
169  coldef->is_from_type = false;
170  coldef->storage = 0;
171  coldef->raw_default = NULL;
172  coldef->cooked_default = NULL;
173  coldef->collClause = NULL;
174  coldef->collOid = InvalidOid;
175  coldef->constraints = NIL;
176  coldef->location = -1;
177 
178  null[i - 1] = false;
179 
180  switch (i)
181  {
182  case SEQ_COL_LASTVAL:
183  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
184  coldef->colname = "last_value";
185  value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
186  break;
187  case SEQ_COL_LOG:
188  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
189  coldef->colname = "log_cnt";
190  value[i - 1] = Int64GetDatum((int64) 0);
191  break;
192  case SEQ_COL_CALLED:
193  coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
194  coldef->colname = "is_called";
195  value[i - 1] = BoolGetDatum(false);
196  break;
197  }
198  stmt->tableElts = lappend(stmt->tableElts, coldef);
199  }
200 
201  stmt->relation = seq->sequence;
202  stmt->inhRelations = NIL;
203  stmt->constraints = NIL;
204  stmt->options = NIL;
205  stmt->oncommit = ONCOMMIT_NOOP;
206  stmt->tablespacename = NULL;
207  stmt->if_not_exists = seq->if_not_exists;
208 
209  address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
210  seqoid = address.objectId;
211  Assert(seqoid != InvalidOid);
212 
213  rel = heap_open(seqoid, AccessExclusiveLock);
214  tupDesc = RelationGetDescr(rel);
215 
216  /* now initialize the sequence's data */
217  tuple = heap_form_tuple(tupDesc, value, null);
218  fill_seq_with_data(rel, tuple);
219 
220  /* process OWNED BY if given */
221  if (owned_by)
222  process_owned_by(rel, owned_by);
223 
224  heap_close(rel, NoLock);
225 
226  /* fill in pg_sequence */
228  tupDesc = RelationGetDescr(rel);
229 
230  memset(pgs_nulls, 0, sizeof(pgs_nulls));
231 
232  pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
233  pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
234  pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
235  pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
236  pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
237  pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
238  pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
239  pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
240 
241  tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
242  CatalogTupleInsert(rel, tuple);
243 
244  heap_freetuple(tuple);
246 
247  return address;
248 }
RangeVar * relation
Definition: parsenodes.h:1894
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: parsenodes.h:1903
List * inhRelations
Definition: parsenodes.h:1896
static struct @76 value
char storage
Definition: parsenodes.h:604
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
bool is_local
Definition: parsenodes.h:601
#define RelationGetDescr(relation)
Definition: rel.h:425
List * constraints
Definition: parsenodes.h:609
bool if_not_exists
Definition: parsenodes.h:2360
#define Anum_pg_sequence_seqcache
Definition: pg_sequence.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SequenceRelationId
Definition: pg_sequence.h:6
#define SEQ_COL_FIRSTCOL
Definition: sequence.h:42
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
bool is_not_null
Definition: parsenodes.h:602
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
#define Anum_pg_sequence_seqtypid
Definition: pg_sequence.h:24
static void process_owned_by(Relation seqrel, List *owned_by)
Definition: sequence.c:1568
List * constraints
Definition: parsenodes.h:1901
bool if_not_exists
Definition: parsenodes.h:1905
Node * cooked_default
Definition: parsenodes.h:606
char * relname
Definition: primnodes.h:67
#define SEQ_COL_LASTVAL
Definition: sequence.h:38
FormData_pg_sequence
Definition: pg_sequence.h:18
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Natts_pg_sequence
Definition: pg_sequence.h:22
#define NoLock
Definition: lockdefs.h:34
Oid collOid
Definition: parsenodes.h:608
#define RowExclusiveLock
Definition: lockdefs.h:38
List * options
Definition: parsenodes.h:1902
int location
Definition: parsenodes.h:611
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:481
#define ereport(elevel, rest)
Definition: elog.h:122
#define SEQ_COL_LOG
Definition: sequence.h:39
Node * raw_default
Definition: parsenodes.h:605
static void init_params(ParseState *pstate, List *options, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, List **owned_by)
Definition: sequence.c:1222
List * lappend(List *list, void *datum)
Definition: list.c:128
char * tablespacename
Definition: parsenodes.h:1904
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:507
uintptr_t Datum
Definition: postgres.h:374
#define Anum_pg_sequence_seqmin
Definition: pg_sequence.h:28
#define Anum_pg_sequence_seqcycle
Definition: pg_sequence.h:30
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define Int64GetDatumFast(X)
Definition: postgres.h:783
#define BoolGetDatum(X)
Definition: postgres.h:410
TypeName * makeTypeNameFromOid(Oid typeOid, int32 typmod)
Definition: makefuncs.c:469
#define InvalidOid
Definition: postgres_ext.h:36
RangeVar * sequence
Definition: parsenodes.h:2357
bool is_from_type
Definition: parsenodes.h:603
#define NOTICE
Definition: elog.h:37
#define INT8OID
Definition: pg_type.h:304
List * tableElts
Definition: parsenodes.h:1895
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
TypeName * typeName
Definition: parsenodes.h:599
CollateClause * collClause
Definition: parsenodes.h:607
#define Anum_pg_sequence_seqstart
Definition: pg_sequence.h:25
#define BOOLOID
Definition: pg_type.h:288
char relpersistence
Definition: primnodes.h:70
#define SEQ_COL_LASTCOL
Definition: sequence.h:43
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SEQ_COL_CALLED
Definition: sequence.h:40
#define Anum_pg_sequence_seqrelid
Definition: pg_sequence.h:23
int i
int inhcount
Definition: parsenodes.h:600
char * colname
Definition: parsenodes.h:598
#define Anum_pg_sequence_seqincrement
Definition: pg_sequence.h:26
#define Anum_pg_sequence_seqmax
Definition: pg_sequence.h:27
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:331
List * options
Definition: parsenodes.h:2358
void DeleteSequenceTuple ( Oid  relid)

Definition at line 516 of file sequence.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1, SEQRELID, SequenceRelationId, and HeapTupleData::t_self.

Referenced by doDeletion().

517 {
518  Relation rel;
519  HeapTuple tuple;
520 
522 
523  tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
524  if (!HeapTupleIsValid(tuple))
525  elog(ERROR, "cache lookup failed for sequence %u", relid);
526 
527  CatalogTupleDelete(rel, &tuple->t_self);
528 
529  ReleaseSysCache(tuple);
531 }
#define SequenceRelationId
Definition: pg_sequence.h:6
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
static void do_setval ( Oid  relid,
int64  next,
bool  iscalled 
)
static

Definition at line 898 of file sequence.c.

References ACL_UPDATE, ACLCHECK_OK, buf, BufferGetPage, SeqTableData::cached, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetTopTransactionId(), GetUserId(), HeapTupleIsValid, init_sequence(), INT64_FORMAT, 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, snprintf(), 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().

899 {
900  SeqTable elm;
901  Relation seqrel;
902  Buffer buf;
903  HeapTupleData seqdatatuple;
905  HeapTuple pgstuple;
906  Form_pg_sequence pgsform;
907  int64 maxv,
908  minv;
909 
910  /* open and AccessShareLock sequence */
911  init_sequence(relid, &elm, &seqrel);
912 
914  ereport(ERROR,
915  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
916  errmsg("permission denied for sequence %s",
917  RelationGetRelationName(seqrel))));
918 
919  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
920  if (!HeapTupleIsValid(pgstuple))
921  elog(ERROR, "cache lookup failed for sequence %u", relid);
922  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
923  maxv = pgsform->seqmax;
924  minv = pgsform->seqmin;
925  ReleaseSysCache(pgstuple);
926 
927  /* read-only transactions may only modify temp sequences */
928  if (!seqrel->rd_islocaltemp)
929  PreventCommandIfReadOnly("setval()");
930 
931  /*
932  * Forbid this during parallel operation because, to make it work, the
933  * cooperating backends would need to share the backend-local cached
934  * sequence information. Currently, we don't support that.
935  */
936  PreventCommandIfParallelMode("setval()");
937 
938  /* lock page' buffer and read tuple */
939  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
940 
941  if ((next < minv) || (next > maxv))
942  {
943  char bufv[100],
944  bufm[100],
945  bufx[100];
946 
947  snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
948  snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
949  snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
950  ereport(ERROR,
951  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
952  errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
953  bufv, RelationGetRelationName(seqrel),
954  bufm, bufx)));
955  }
956 
957  /* Set the currval() state only if iscalled = true */
958  if (iscalled)
959  {
960  elm->last = next; /* last returned number */
961  elm->last_valid = true;
962  }
963 
964  /* In any case, forget any future cached numbers */
965  elm->cached = elm->last;
966 
967  /* check the comment above nextval_internal()'s equivalent call. */
968  if (RelationNeedsWAL(seqrel))
970 
971  /* ready to change the on-disk (or really, in-buffer) tuple */
973 
974  seq->last_value = next; /* last fetched number */
975  seq->is_called = iscalled;
976  seq->log_cnt = 0;
977 
978  MarkBufferDirty(buf);
979 
980  /* XLOG stuff */
981  if (RelationNeedsWAL(seqrel))
982  {
983  xl_seq_rec xlrec;
984  XLogRecPtr recptr;
985  Page page = BufferGetPage(buf);
986 
987  XLogBeginInsert();
989 
990  xlrec.node = seqrel->rd_node;
991  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
992  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
993 
994  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
995 
996  PageSetLSN(page, recptr);
997  }
998 
1000 
1001  UnlockReleaseBuffer(buf);
1002 
1003  relation_close(seqrel, NoLock);
1004 }
int64 cached
Definition: sequence.c:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static int32 next
Definition: blutils.c:210
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:253
Oid GetUserId(void)
Definition: miscinit.c:283
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
bool last_valid
Definition: sequence.c:77
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
bool rd_islocaltemp
Definition: rel.h:90
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
RelFileNode node
Definition: sequence.h:50
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:65
#define RelationGetRelationName(relation)
Definition: rel.h:433
int64 last
Definition: sequence.c:78
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1167
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define ACL_UPDATE
Definition: parsenodes.h:67
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define RelationNeedsWAL(relation)
Definition: rel.h:502
#define INT64_FORMAT
Definition: c.h:312
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:235
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
static void fill_seq_with_data ( Relation  rel,
HeapTuple  tuple 
)
static

Definition at line 331 of file sequence.c.

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, InvalidOffsetNumber, InvalidTransactionId, ItemPointerSet, LockBuffer(), sequence_magic::magic, MarkBufferDirty(), xl_seq_rec::node, P_NEW, PageAddItem, PageGetSpecialPointer, PageInit(), PageSetLSN, RelationData::rd_node, ReadBuffer(), 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 DefineSequence(), and ResetSequence().

332 {
333  Buffer buf;
334  Page page;
335  sequence_magic *sm;
336  OffsetNumber offnum;
337 
338  /* Initialize first page of relation with special magic number */
339 
340  buf = ReadBuffer(rel, P_NEW);
341  Assert(BufferGetBlockNumber(buf) == 0);
342 
343  page = BufferGetPage(buf);
344 
345  PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
346  sm = (sequence_magic *) PageGetSpecialPointer(page);
347  sm->magic = SEQ_MAGIC;
348 
349  /* Now insert sequence tuple */
350 
352 
353  /*
354  * Since VACUUM does not process sequences, we have to force the tuple to
355  * have xmin = FrozenTransactionId now. Otherwise it would become
356  * invisible to SELECTs after 2G transactions. It is okay to do this
357  * because if the current transaction aborts, no other xact will ever
358  * examine the sequence tuple anyway.
359  */
366 
367  /* check the comment above nextval_internal()'s equivalent call. */
368  if (RelationNeedsWAL(rel))
370 
372 
373  MarkBufferDirty(buf);
374 
375  offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
376  InvalidOffsetNumber, false, false);
377  if (offnum != FirstOffsetNumber)
378  elog(ERROR, "failed to add sequence tuple to page");
379 
380  /* XLOG stuff */
381  if (RelationNeedsWAL(rel))
382  {
383  xl_seq_rec xlrec;
384  XLogRecPtr recptr;
385 
386  XLogBeginInsert();
388 
389  xlrec.node = rel->rd_node;
390 
391  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
392  XLogRegisterData((char *) tuple->t_data, tuple->t_len);
393 
394  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
395 
396  PageSetLSN(page, recptr);
397  }
398 
400 
401  UnlockReleaseBuffer(buf);
402 }
#define SEQ_MAGIC
Definition: sequence.c:59
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
Pointer Item
Definition: item.h:17
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:413
#define P_NEW
Definition: bufmgr.h:82
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
RelFileNode node
Definition: sequence.h:50
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define FirstCommandId
Definition: c.h:410
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_ctid
Definition: htup_details.h:150
uint32 t_len
Definition: htup.h:64
static char * buf
Definition: pg_test_fsync.c:65
#define FirstOffsetNumber
Definition: off.h:27
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
#define InvalidTransactionId
Definition: transam.h:31
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define InvalidOffsetNumber
Definition: off.h:26
RelFileNode rd_node
Definition: rel.h:85
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:671
#define FrozenTransactionId
Definition: transam.h:33
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint32 magic
Definition: sequence.c:63
#define PageGetSpecialPointer(page)
Definition: bufpage.h:323
#define RelationNeedsWAL(relation)
Definition: rel.h:502
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2588
#define HeapTupleHeaderSetXminFrozen(tup)
Definition: htup_details.h:346
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:391
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:86
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:313
static void init_params ( ParseState pstate,
List options,
bool  isInit,
Form_pg_sequence  seqform,
Form_pg_sequence_data  seqdataform,
List **  owned_by 
)
static

Definition at line 1222 of file sequence.c.

References DefElem::arg, Assert, BoolIsValid, buf, defGetInt64(), defGetQualifiedName(), defGetTypeName(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), INT2OID, INT4OID, INT64_FORMAT, INT8OID, intVal, FormData_pg_sequence_data::is_called, FormData_pg_sequence_data::last_value, lfirst, DefElem::location, FormData_pg_sequence_data::log_cnt, NIL, NULL, parser_errposition(), PG_INT16_MAX, PG_INT16_MIN, PG_INT32_MAX, PG_INT32_MIN, PG_INT64_MAX, PG_INT64_MIN, snprintf(), and typenameTypeId().

Referenced by AlterSequence(), and DefineSequence().

1225 {
1226  DefElem *as_type = NULL;
1227  DefElem *start_value = NULL;
1228  DefElem *restart_value = NULL;
1229  DefElem *increment_by = NULL;
1230  DefElem *max_value = NULL;
1231  DefElem *min_value = NULL;
1232  DefElem *cache_value = NULL;
1233  DefElem *is_cycled = NULL;
1234  ListCell *option;
1235 
1236  *owned_by = NIL;
1237 
1238  foreach(option, options)
1239  {
1240  DefElem *defel = (DefElem *) lfirst(option);
1241 
1242  if (strcmp(defel->defname, "as") == 0)
1243  {
1244  if (as_type)
1245  ereport(ERROR,
1246  (errcode(ERRCODE_SYNTAX_ERROR),
1247  errmsg("conflicting or redundant options"),
1248  parser_errposition(pstate, defel->location)));
1249  as_type = defel;
1250  }
1251  else if (strcmp(defel->defname, "increment") == 0)
1252  {
1253  if (increment_by)
1254  ereport(ERROR,
1255  (errcode(ERRCODE_SYNTAX_ERROR),
1256  errmsg("conflicting or redundant options"),
1257  parser_errposition(pstate, defel->location)));
1258  increment_by = defel;
1259  }
1260  else if (strcmp(defel->defname, "start") == 0)
1261  {
1262  if (start_value)
1263  ereport(ERROR,
1264  (errcode(ERRCODE_SYNTAX_ERROR),
1265  errmsg("conflicting or redundant options"),
1266  parser_errposition(pstate, defel->location)));
1267  start_value = defel;
1268  }
1269  else if (strcmp(defel->defname, "restart") == 0)
1270  {
1271  if (restart_value)
1272  ereport(ERROR,
1273  (errcode(ERRCODE_SYNTAX_ERROR),
1274  errmsg("conflicting or redundant options"),
1275  parser_errposition(pstate, defel->location)));
1276  restart_value = defel;
1277  }
1278  else if (strcmp(defel->defname, "maxvalue") == 0)
1279  {
1280  if (max_value)
1281  ereport(ERROR,
1282  (errcode(ERRCODE_SYNTAX_ERROR),
1283  errmsg("conflicting or redundant options"),
1284  parser_errposition(pstate, defel->location)));
1285  max_value = defel;
1286  }
1287  else if (strcmp(defel->defname, "minvalue") == 0)
1288  {
1289  if (min_value)
1290  ereport(ERROR,
1291  (errcode(ERRCODE_SYNTAX_ERROR),
1292  errmsg("conflicting or redundant options"),
1293  parser_errposition(pstate, defel->location)));
1294  min_value = defel;
1295  }
1296  else if (strcmp(defel->defname, "cache") == 0)
1297  {
1298  if (cache_value)
1299  ereport(ERROR,
1300  (errcode(ERRCODE_SYNTAX_ERROR),
1301  errmsg("conflicting or redundant options"),
1302  parser_errposition(pstate, defel->location)));
1303  cache_value = defel;
1304  }
1305  else if (strcmp(defel->defname, "cycle") == 0)
1306  {
1307  if (is_cycled)
1308  ereport(ERROR,
1309  (errcode(ERRCODE_SYNTAX_ERROR),
1310  errmsg("conflicting or redundant options"),
1311  parser_errposition(pstate, defel->location)));
1312  is_cycled = defel;
1313  }
1314  else if (strcmp(defel->defname, "owned_by") == 0)
1315  {
1316  if (*owned_by)
1317  ereport(ERROR,
1318  (errcode(ERRCODE_SYNTAX_ERROR),
1319  errmsg("conflicting or redundant options"),
1320  parser_errposition(pstate, defel->location)));
1321  *owned_by = defGetQualifiedName(defel);
1322  }
1323  else
1324  elog(ERROR, "option \"%s\" not recognized",
1325  defel->defname);
1326  }
1327 
1328  /*
1329  * We must reset log_cnt when isInit or when changing any parameters that
1330  * would affect future nextval allocations.
1331  */
1332  if (isInit)
1333  seqdataform->log_cnt = 0;
1334 
1335  /* AS type */
1336  if (as_type != NULL)
1337  {
1338  seqform->seqtypid = typenameTypeId(pstate, defGetTypeName(as_type));
1339  if (seqform->seqtypid != INT2OID &&
1340  seqform->seqtypid != INT4OID &&
1341  seqform->seqtypid != INT8OID)
1342  ereport(ERROR,
1343  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1344  errmsg("sequence type must be smallint, integer, or bigint")));
1345  }
1346  else if (isInit)
1347  seqform->seqtypid = INT8OID;
1348 
1349  /* INCREMENT BY */
1350  if (increment_by != NULL)
1351  {
1352  seqform->seqincrement = defGetInt64(increment_by);
1353  if (seqform->seqincrement == 0)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1356  errmsg("INCREMENT must not be zero")));
1357  seqdataform->log_cnt = 0;
1358  }
1359  else if (isInit)
1360  seqform->seqincrement = 1;
1361 
1362  /* CYCLE */
1363  if (is_cycled != NULL)
1364  {
1365  seqform->seqcycle = intVal(is_cycled->arg);
1366  Assert(BoolIsValid(seqform->seqcycle));
1367  seqdataform->log_cnt = 0;
1368  }
1369  else if (isInit)
1370  seqform->seqcycle = false;
1371 
1372  /* MAXVALUE (null arg means NO MAXVALUE) */
1373  if (max_value != NULL && max_value->arg)
1374  {
1375  seqform->seqmax = defGetInt64(max_value);
1376  seqdataform->log_cnt = 0;
1377  }
1378  else if (isInit || max_value != NULL)
1379  {
1380  if (seqform->seqincrement > 0)
1381  {
1382  /* ascending seq */
1383  if (seqform->seqtypid == INT2OID)
1384  seqform->seqmax = PG_INT16_MAX;
1385  else if (seqform->seqtypid == INT4OID)
1386  seqform->seqmax = PG_INT32_MAX;
1387  else
1388  seqform->seqmax = PG_INT64_MAX;
1389  }
1390  else
1391  seqform->seqmax = -1; /* descending seq */
1392  seqdataform->log_cnt = 0;
1393  }
1394 
1395  if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
1396  || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX))
1397  || (seqform->seqtypid == INT8OID && (seqform->seqmax < PG_INT64_MIN || seqform->seqmax > PG_INT64_MAX)))
1398  {
1399  char bufx[100];
1400 
1401  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1402 
1403  ereport(ERROR,
1404  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1405  errmsg("MAXVALUE (%s) is out of range for sequence data type %s",
1406  bufx, format_type_be(seqform->seqtypid))));
1407  }
1408 
1409  /* MINVALUE (null arg means NO MINVALUE) */
1410  if (min_value != NULL && min_value->arg)
1411  {
1412  seqform->seqmin = defGetInt64(min_value);
1413  seqdataform->log_cnt = 0;
1414  }
1415  else if (isInit || min_value != NULL)
1416  {
1417  if (seqform->seqincrement > 0)
1418  seqform->seqmin = 1; /* ascending seq */
1419  else
1420  {
1421  /* descending seq */
1422  if (seqform->seqtypid == INT2OID)
1423  seqform->seqmin = PG_INT16_MIN;
1424  else if (seqform->seqtypid == INT4OID)
1425  seqform->seqmin = PG_INT32_MIN;
1426  else
1427  seqform->seqmin = PG_INT64_MIN;
1428  }
1429  seqdataform->log_cnt = 0;
1430  }
1431 
1432  if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
1433  || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX))
1434  || (seqform->seqtypid == INT8OID && (seqform->seqmin < PG_INT64_MIN || seqform->seqmin > PG_INT64_MAX)))
1435  {
1436  char bufm[100];
1437 
1438  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1439 
1440  ereport(ERROR,
1441  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1442  errmsg("MINVALUE (%s) is out of range for sequence data type %s",
1443  bufm, format_type_be(seqform->seqtypid))));
1444  }
1445 
1446  /* crosscheck min/max */
1447  if (seqform->seqmin >= seqform->seqmax)
1448  {
1449  char bufm[100],
1450  bufx[100];
1451 
1452  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1453  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1454  ereport(ERROR,
1455  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1456  errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
1457  bufm, bufx)));
1458  }
1459 
1460  /* START WITH */
1461  if (start_value != NULL)
1462  seqform->seqstart = defGetInt64(start_value);
1463  else if (isInit)
1464  {
1465  if (seqform->seqincrement > 0)
1466  seqform->seqstart = seqform->seqmin; /* ascending seq */
1467  else
1468  seqform->seqstart = seqform->seqmax; /* descending seq */
1469  }
1470 
1471  /* crosscheck START */
1472  if (seqform->seqstart < seqform->seqmin)
1473  {
1474  char bufs[100],
1475  bufm[100];
1476 
1477  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1478  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1479  ereport(ERROR,
1480  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1481  errmsg("START value (%s) cannot be less than MINVALUE (%s)",
1482  bufs, bufm)));
1483  }
1484  if (seqform->seqstart > seqform->seqmax)
1485  {
1486  char bufs[100],
1487  bufm[100];
1488 
1489  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1490  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1491  ereport(ERROR,
1492  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1493  errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
1494  bufs, bufm)));
1495  }
1496 
1497  /* RESTART [WITH] */
1498  if (restart_value != NULL)
1499  {
1500  if (restart_value->arg != NULL)
1501  seqdataform->last_value = defGetInt64(restart_value);
1502  else
1503  seqdataform->last_value = seqform->seqstart;
1504  seqdataform->is_called = false;
1505  seqdataform->log_cnt = 0;
1506  }
1507  else if (isInit)
1508  {
1509  seqdataform->last_value = seqform->seqstart;
1510  seqdataform->is_called = false;
1511  }
1512 
1513  /* crosscheck RESTART (or current value, if changing MIN/MAX) */
1514  if (seqdataform->last_value < seqform->seqmin)
1515  {
1516  char bufs[100],
1517  bufm[100];
1518 
1519  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1520  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1521  ereport(ERROR,
1522  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1523  errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
1524  bufs, bufm)));
1525  }
1526  if (seqdataform->last_value > seqform->seqmax)
1527  {
1528  char bufs[100],
1529  bufm[100];
1530 
1531  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1532  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1533  ereport(ERROR,
1534  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1535  errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
1536  bufs, bufm)));
1537  }
1538 
1539  /* CACHE */
1540  if (cache_value != NULL)
1541  {
1542  seqform->seqcache = defGetInt64(cache_value);
1543  if (seqform->seqcache <= 0)
1544  {
1545  char buf[100];
1546 
1547  snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
1548  ereport(ERROR,
1549  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1550  errmsg("CACHE (%s) must be greater than zero",
1551  buf)));
1552  }
1553  seqdataform->log_cnt = 0;
1554  }
1555  else if (isInit)
1556  seqform->seqcache = 1;
1557 }
#define NIL
Definition: pg_list.h:69
#define PG_INT64_MAX
Definition: c.h:340
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
int64 defGetInt64(DefElem *def)
Definition: define.c:190
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
#define ERROR
Definition: elog.h:43
#define INT2OID
Definition: pg_type.h:308
static char * buf
Definition: pg_test_fsync.c:65
#define PG_INT64_MIN
Definition: c.h:339
int location
Definition: parsenodes.h:678
#define PG_INT16_MIN
Definition: c.h:333
#define PG_INT32_MIN
Definition: c.h:336
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:676
#define INT8OID
Definition: pg_type.h:304
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
#define PG_INT16_MAX
Definition: c.h:334
#define INT64_FORMAT
Definition: c.h:312
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_INT32_MAX
Definition: c.h:337
char * defname
Definition: parsenodes.h:675
#define elog
Definition: elog.h:219
#define BoolIsValid(boolean)
Definition: c.h:516
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
static void init_sequence ( Oid  relid,
SeqTable p_elm,
Relation p_rel 
)
static

Definition at line 1100 of file sequence.c.

References SeqTableData::cached, create_seq_hashtable(), ereport, errcode(), errmsg(), ERROR, SeqTableData::filenode, HASH_ENTER, hash_search(), InvalidLocalTransactionId, InvalidOid, SeqTableData::last, SeqTableData::last_valid, SeqTableData::lxid, NULL, open_share_lock(), RelationData::rd_rel, RelationGetRelationName, and RELKIND_SEQUENCE.

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

1101 {
1102  SeqTable elm;
1103  Relation seqrel;
1104  bool found;
1105 
1106  /* Find or create a hash table entry for this sequence */
1107  if (seqhashtab == NULL)
1109 
1110  elm = (SeqTable) hash_search(seqhashtab, &relid, HASH_ENTER, &found);
1111 
1112  /*
1113  * Initialize the new hash table entry if it did not exist already.
1114  *
1115  * NOTE: seqtable entries are stored for the life of a backend (unless
1116  * explicitly discarded with DISCARD). If the sequence itself is deleted
1117  * then the entry becomes wasted memory, but it's small enough that this
1118  * should not matter.
1119  */
1120  if (!found)
1121  {
1122  /* relid already filled in */
1123  elm->filenode = InvalidOid;
1125  elm->last_valid = false;
1126  elm->last = elm->cached = 0;
1127  }
1128 
1129  /*
1130  * Open the sequence relation.
1131  */
1132  seqrel = open_share_lock(elm);
1133 
1134  if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
1135  ereport(ERROR,
1136  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1137  errmsg("\"%s\" is not a sequence",
1138  RelationGetRelationName(seqrel))));
1139 
1140  /*
1141  * If the sequence has been transactionally replaced since we last saw it,
1142  * discard any cached-but-unissued values. We do not touch the currval()
1143  * state, however.
1144  */
1145  if (seqrel->rd_rel->relfilenode != elm->filenode)
1146  {
1147  elm->filenode = seqrel->rd_rel->relfilenode;
1148  elm->cached = elm->last;
1149  }
1150 
1151  /* Return results */
1152  *p_elm = elm;
1153  *p_rel = seqrel;
1154 }
int64 cached
Definition: sequence.c:79
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
Form_pg_class rd_rel
Definition: rel.h:113
static HTAB * seqhashtab
Definition: sequence.c:87
#define ERROR
Definition: elog.h:43
static void create_seq_hashtable(void)
Definition: sequence.c:1083
static Relation open_share_lock(SeqTable seq)
Definition: sequence.c:1047
#define RelationGetRelationName(relation)
Definition: rel.h:433
int64 last
Definition: sequence.c:78
#define ereport(elevel, rest)
Definition: elog.h:122
SeqTableData * SeqTable
Definition: sequence.c:85
Oid filenode
Definition: sequence.c:75
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
LocalTransactionId lxid
Definition: sequence.c:76
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define InvalidLocalTransactionId
Definition: lock.h:70
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Datum lastval ( PG_FUNCTION_ARGS  )

Definition at line 850 of file sequence.c.

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

851 {
852  Relation seqrel;
853  int64 result;
854 
855  if (last_used_seq == NULL)
856  ereport(ERROR,
857  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
858  errmsg("lastval is not yet defined in this session")));
859 
860  /* Someone may have dropped the sequence since the last nextval() */
862  ereport(ERROR,
863  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
864  errmsg("lastval is not yet defined in this session")));
865 
866  seqrel = open_share_lock(last_used_seq);
867 
868  /* nextval() must have already been called for this sequence */
870 
873  ereport(ERROR,
874  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
875  errmsg("permission denied for sequence %s",
876  RelationGetRelationName(seqrel))));
877 
878  result = last_used_seq->last;
879  relation_close(seqrel, NoLock);
880 
881  PG_RETURN_INT64(result);
882 }
Oid GetUserId(void)
Definition: miscinit.c:283
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:167
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
static Relation open_share_lock(SeqTable seq)
Definition: sequence.c:1047
#define NoLock
Definition: lockdefs.h:34
#define RelationGetRelationName(relation)
Definition: rel.h:433
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:73
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_SELECT
Definition: parsenodes.h:66
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static SeqTableData * last_used_seq
Definition: sequence.c:93
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum nextval ( PG_FUNCTION_ARGS  )

Definition at line 539 of file sequence.c.

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

Referenced by autoinc(), and ttdummy().

540 {
541  text *seqin = PG_GETARG_TEXT_P(0);
542  RangeVar *sequence;
543  Oid relid;
544 
546 
547  /*
548  * XXX: This is not safe in the presence of concurrent DDL, but acquiring
549  * a lock here is more expensive than letting nextval_internal do it,
550  * since the latter maintains a cache that keeps us from hitting the lock
551  * manager more than once per transaction. It's not clear whether the
552  * performance penalty is material in practice, but for now, we do it this
553  * way.
554  */
555  relid = RangeVarGetRelid(sequence, NoLock, false);
556 
558 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2857
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3071
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
static int64 nextval_internal(Oid relid)
Definition: sequence.c:569
static int64 nextval_internal ( Oid  relid)
static

Definition at line 569 of file sequence.c.

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(), INT64_FORMAT, 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, 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, snprintf(), START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by nextval(), and nextval_oid().

570 {
571  SeqTable elm;
572  Relation seqrel;
573  Buffer buf;
574  Page page;
575  HeapTuple pgstuple;
576  Form_pg_sequence pgsform;
577  HeapTupleData seqdatatuple;
579  int64 incby,
580  maxv,
581  minv,
582  cache,
583  log,
584  fetch,
585  last;
586  int64 result,
587  next,
588  rescnt = 0;
589  bool cycle;
590  bool logit = false;
591 
592  /* open and AccessShareLock sequence */
593  init_sequence(relid, &elm, &seqrel);
594 
595  if (pg_class_aclcheck(elm->relid, GetUserId(),
597  ereport(ERROR,
598  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
599  errmsg("permission denied for sequence %s",
600  RelationGetRelationName(seqrel))));
601 
602  /* read-only transactions may only modify temp sequences */
603  if (!seqrel->rd_islocaltemp)
604  PreventCommandIfReadOnly("nextval()");
605 
606  /*
607  * Forbid this during parallel operation because, to make it work, the
608  * cooperating backends would need to share the backend-local cached
609  * sequence information. Currently, we don't support that.
610  */
611  PreventCommandIfParallelMode("nextval()");
612 
613  if (elm->last != elm->cached) /* some numbers were cached */
614  {
615  Assert(elm->last_valid);
616  Assert(elm->increment != 0);
617  elm->last += elm->increment;
618  relation_close(seqrel, NoLock);
619  last_used_seq = elm;
620  return elm->last;
621  }
622 
623  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
624  if (!HeapTupleIsValid(pgstuple))
625  elog(ERROR, "cache lookup failed for sequence %u", relid);
626  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
627  incby = pgsform->seqincrement;
628  maxv = pgsform->seqmax;
629  minv = pgsform->seqmin;
630  cache = pgsform->seqcache;
631  cycle = pgsform->seqcycle;
632  ReleaseSysCache(pgstuple);
633 
634  /* lock page' buffer and read tuple */
635  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
636  page = BufferGetPage(buf);
637 
638  elm->increment = incby;
639  last = next = result = seq->last_value;
640  fetch = cache;
641  log = seq->log_cnt;
642 
643  if (!seq->is_called)
644  {
645  rescnt++; /* return last_value if not is_called */
646  fetch--;
647  }
648 
649  /*
650  * Decide whether we should emit a WAL log record. If so, force up the
651  * fetch count to grab SEQ_LOG_VALS more values than we actually need to
652  * cache. (These will then be usable without logging.)
653  *
654  * If this is the first nextval after a checkpoint, we must force a new
655  * WAL record to be written anyway, else replay starting from the
656  * checkpoint would fail to advance the sequence past the logged values.
657  * In this case we may as well fetch extra values.
658  */
659  if (log < fetch || !seq->is_called)
660  {
661  /* forced log to satisfy local demand for values */
662  fetch = log = fetch + SEQ_LOG_VALS;
663  logit = true;
664  }
665  else
666  {
667  XLogRecPtr redoptr = GetRedoRecPtr();
668 
669  if (PageGetLSN(page) <= redoptr)
670  {
671  /* last update of seq was before checkpoint */
672  fetch = log = fetch + SEQ_LOG_VALS;
673  logit = true;
674  }
675  }
676 
677  while (fetch) /* try to fetch cache [+ log ] numbers */
678  {
679  /*
680  * Check MAXVALUE for ascending sequences and MINVALUE for descending
681  * sequences
682  */
683  if (incby > 0)
684  {
685  /* ascending sequence */
686  if ((maxv >= 0 && next > maxv - incby) ||
687  (maxv < 0 && next + incby > maxv))
688  {
689  if (rescnt > 0)
690  break; /* stop fetching */
691  if (!cycle)
692  {
693  char buf[100];
694 
695  snprintf(buf, sizeof(buf), INT64_FORMAT, maxv);
696  ereport(ERROR,
697  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
698  errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",
699  RelationGetRelationName(seqrel), buf)));
700  }
701  next = minv;
702  }
703  else
704  next += incby;
705  }
706  else
707  {
708  /* descending sequence */
709  if ((minv < 0 && next < minv - incby) ||
710  (minv >= 0 && next + incby < minv))
711  {
712  if (rescnt > 0)
713  break; /* stop fetching */
714  if (!cycle)
715  {
716  char buf[100];
717 
718  snprintf(buf, sizeof(buf), INT64_FORMAT, minv);
719  ereport(ERROR,
720  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
721  errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",
722  RelationGetRelationName(seqrel), buf)));
723  }
724  next = maxv;
725  }
726  else
727  next += incby;
728  }
729  fetch--;
730  if (rescnt < cache)
731  {
732  log--;
733  rescnt++;
734  last = next;
735  if (rescnt == 1) /* if it's first result - */
736  result = next; /* it's what to return */
737  }
738  }
739 
740  log -= fetch; /* adjust for any unfetched numbers */
741  Assert(log >= 0);
742 
743  /* save info in local cache */
744  elm->last = result; /* last returned number */
745  elm->cached = last; /* last fetched number */
746  elm->last_valid = true;
747 
748  last_used_seq = elm;
749 
750  /*
751  * If something needs to be WAL logged, acquire an xid, so this
752  * transaction's commit will trigger a WAL flush and wait for syncrep.
753  * It's sufficient to ensure the toplevel transaction has an xid, no need
754  * to assign xids subxacts, that'll already trigger an appropriate wait.
755  * (Have to do that here, so we're outside the critical section)
756  */
757  if (logit && RelationNeedsWAL(seqrel))
759 
760  /* ready to change the on-disk (or really, in-buffer) tuple */
762 
763  /*
764  * We must mark the buffer dirty before doing XLogInsert(); see notes in
765  * SyncOneBuffer(). However, we don't apply the desired changes just yet.
766  * This looks like a violation of the buffer update protocol, but it is in
767  * fact safe because we hold exclusive lock on the buffer. Any other
768  * process, including a checkpoint, that tries to examine the buffer
769  * contents will block until we release the lock, and then will see the
770  * final state that we install below.
771  */
772  MarkBufferDirty(buf);
773 
774  /* XLOG stuff */
775  if (logit && RelationNeedsWAL(seqrel))
776  {
777  xl_seq_rec xlrec;
778  XLogRecPtr recptr;
779 
780  /*
781  * We don't log the current state of the tuple, but rather the state
782  * as it would appear after "log" more fetches. This lets us skip
783  * that many future WAL records, at the cost that we lose those
784  * sequence values if we crash.
785  */
786  XLogBeginInsert();
788 
789  /* set values that will be saved in xlog */
790  seq->last_value = next;
791  seq->is_called = true;
792  seq->log_cnt = 0;
793 
794  xlrec.node = seqrel->rd_node;
795 
796  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
797  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
798 
799  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
800 
801  PageSetLSN(page, recptr);
802  }
803 
804  /* Now update sequence tuple to the intended final state */
805  seq->last_value = last; /* last fetched number */
806  seq->is_called = true;
807  seq->log_cnt = log; /* how much is logged */
808 
810 
811  UnlockReleaseBuffer(buf);
812 
813  relation_close(seqrel, NoLock);
814 
815  return result;
816 }
int64 cached
Definition: sequence.c:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static int32 next
Definition: blutils.c:210
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:253
Oid GetUserId(void)
Definition: miscinit.c:283
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
bool last_valid
Definition: sequence.c:77
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
bool rd_islocaltemp
Definition: rel.h:90
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
RelFileNode node
Definition: sequence.h:50
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:65
#define RelationGetRelationName(relation)
Definition: rel.h:433
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:73
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1167
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define ACL_UPDATE
Definition: parsenodes.h:67
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:671
#define SEQ_LOG_VALS
Definition: sequence.c:54
int64 increment
Definition: sequence.c:81
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8095
#define RelationNeedsWAL(relation)
Definition: rel.h:502
#define INT64_FORMAT
Definition: c.h:312
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:235
static SeqTableData * last_used_seq
Definition: sequence.c:93
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
#define PageGetLSN(page)
Definition: bufpage.h:363
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
Datum nextval_oid ( PG_FUNCTION_ARGS  )

Definition at line 561 of file sequence.c.

References nextval_internal(), PG_GETARG_OID, and PG_RETURN_INT64.

562 {
563  Oid relid = PG_GETARG_OID(0);
564 
566 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static int64 nextval_internal(Oid relid)
Definition: sequence.c:569
static Relation open_share_lock ( SeqTable  seq)
static

Definition at line 1047 of file sequence.c.

References AccessShareLock, CurrentResourceOwner, LockRelationOid(), SeqTableData::lxid, PGPROC::lxid, MyProc, NoLock, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, relation_open(), SeqTableData::relid, and TopTransactionResourceOwner.

Referenced by init_sequence(), and lastval().

1048 {
1049  LocalTransactionId thislxid = MyProc->lxid;
1050 
1051  /* Get the lock if not already held in this xact */
1052  if (seq->lxid != thislxid)
1053  {
1054  ResourceOwner currentOwner;
1055 
1056  currentOwner = CurrentResourceOwner;
1057  PG_TRY();
1058  {
1061  }
1062  PG_CATCH();
1063  {
1064  /* Ensure CurrentResourceOwner is restored on error */
1065  CurrentResourceOwner = currentOwner;
1066  PG_RE_THROW();
1067  }
1068  PG_END_TRY();
1069  CurrentResourceOwner = currentOwner;
1070 
1071  /* Flag that we have a lock in the current xact */
1072  seq->lxid = thislxid;
1073  }
1074 
1075  /* We now know we have AccessShareLock, and can safely open the rel */
1076  return relation_open(seq->relid, NoLock);
1077 }
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
PGPROC * MyProc
Definition: proc.c:67
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
#define AccessShareLock
Definition: lockdefs.h:36
#define NoLock
Definition: lockdefs.h:34
uint32 LocalTransactionId
Definition: c.h:396
#define PG_CATCH()
Definition: elog.h:293
#define PG_RE_THROW()
Definition: elog.h:314
LocalTransactionId lxid
Definition: sequence.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
LocalTransactionId lxid
Definition: proc.h:95
Datum pg_sequence_last_value ( PG_FUNCTION_ARGS  )

Definition at line 1718 of file sequence.c.

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

1719 {
1720  Oid relid = PG_GETARG_OID(0);
1721  SeqTable elm;
1722  Relation seqrel;
1723  Buffer buf;
1724  HeapTupleData seqtuple;
1726  bool is_called;
1727  int64 result;
1728 
1729  /* open and AccessShareLock sequence */
1730  init_sequence(relid, &elm, &seqrel);
1731 
1733  ereport(ERROR,
1734  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1735  errmsg("permission denied for sequence %s",
1736  RelationGetRelationName(seqrel))));
1737 
1738  seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1739 
1740  is_called = seq->is_called;
1741  result = seq->last_value;
1742 
1743  UnlockReleaseBuffer(buf);
1744  relation_close(seqrel, NoLock);
1745 
1746  if (is_called)
1747  PG_RETURN_INT64(result);
1748  else
1749  PG_RETURN_NULL();
1750 }
Oid GetUserId(void)
Definition: miscinit.c:283
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
unsigned int Oid
Definition: postgres_ext.h:31
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ACL_USAGE
Definition: parsenodes.h:73
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1167
#define ACL_SELECT
Definition: parsenodes.h:66
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
int errmsg(const char *fmt,...)
Definition: elog.c:797
int Buffer
Definition: buf.h:23
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum pg_sequence_parameters ( PG_FUNCTION_ARGS  )

Definition at line 1659 of file sequence.c.

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

1660 {
1661  Oid relid = PG_GETARG_OID(0);
1662  TupleDesc tupdesc;
1663  Datum values[7];
1664  bool isnull[7];
1665  HeapTuple pgstuple;
1666  Form_pg_sequence pgsform;
1667 
1669  ereport(ERROR,
1670  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1671  errmsg("permission denied for sequence %s",
1672  get_rel_name(relid))));
1673 
1674  tupdesc = CreateTemplateTupleDesc(7, false);
1675  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
1676  INT8OID, -1, 0);
1677  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
1678  INT8OID, -1, 0);
1679  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
1680  INT8OID, -1, 0);
1681  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
1682  INT8OID, -1, 0);
1683  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
1684  BOOLOID, -1, 0);
1685  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size",
1686  INT8OID, -1, 0);
1687  TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type",
1688  OIDOID, -1, 0);
1689 
1690  BlessTupleDesc(tupdesc);
1691 
1692  memset(isnull, 0, sizeof(isnull));
1693 
1694  pgstuple = SearchSysCache1(SEQRELID, relid);
1695  if (!HeapTupleIsValid(pgstuple))
1696  elog(ERROR, "cache lookup failed for sequence %u", relid);
1697  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1698 
1699  values[0] = Int64GetDatum(pgsform->seqstart);
1700  values[1] = Int64GetDatum(pgsform->seqmin);
1701  values[2] = Int64GetDatum(pgsform->seqmax);
1702  values[3] = Int64GetDatum(pgsform->seqincrement);
1703  values[4] = BoolGetDatum(pgsform->seqcycle);
1704  values[5] = Int64GetDatum(pgsform->seqcache);
1705  values[6] = ObjectIdGetDatum(pgsform->seqtypid);
1706 
1707  ReleaseSysCache(pgstuple);
1708 
1709  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
1710 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:283
#define OIDOID
Definition: pg_type.h:328
int errcode(int sqlerrcode)
Definition: elog.c:575
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define ACL_USAGE
Definition: parsenodes.h:73
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:493
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_UPDATE
Definition: parsenodes.h:67
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define ACL_SELECT
Definition: parsenodes.h:66
#define BoolGetDatum(X)
Definition: postgres.h:410
#define INT8OID
Definition: pg_type.h:304
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define BOOLOID
Definition: pg_type.h:288
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
int16 AttrNumber
Definition: attnum.h:21
static void process_owned_by ( Relation  seqrel,
List owned_by 
)
static

Definition at line 1568 of file sequence.c.

References AccessShareLock, Assert, ObjectAddress::classId, DEPENDENCY_AUTO, ereport, errcode(), errhint(), errmsg(), ERROR, get_attnum(), InvalidAttrNumber, lfirst, linitial, list_copy(), list_length(), list_tail(), list_truncate(), makeRangeVarFromNameList(), markSequenceUnowned(), NoLock, NULL, ObjectAddress::objectId, ObjectAddress::objectSubId, RelationData::rd_rel, recordDependencyOn(), relation_close(), relation_openrv(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RelationRelationId, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, and strVal.

Referenced by AlterSequence(), and DefineSequence().

1569 {
1570  int nnames;
1571  Relation tablerel;
1572  AttrNumber attnum;
1573 
1574  nnames = list_length(owned_by);
1575  Assert(nnames > 0);
1576  if (nnames == 1)
1577  {
1578  /* Must be OWNED BY NONE */
1579  if (strcmp(strVal(linitial(owned_by)), "none") != 0)
1580  ereport(ERROR,
1581  (errcode(ERRCODE_SYNTAX_ERROR),
1582  errmsg("invalid OWNED BY option"),
1583  errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
1584  tablerel = NULL;
1585  attnum = 0;
1586  }
1587  else
1588  {
1589  List *relname;
1590  char *attrname;
1591  RangeVar *rel;
1592 
1593  /* Separate relname and attr name */
1594  relname = list_truncate(list_copy(owned_by), nnames - 1);
1595  attrname = strVal(lfirst(list_tail(owned_by)));
1596 
1597  /* Open and lock rel to ensure it won't go away meanwhile */
1598  rel = makeRangeVarFromNameList(relname);
1599  tablerel = relation_openrv(rel, AccessShareLock);
1600 
1601  /* Must be a regular or foreign table */
1602  if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
1603  tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1604  tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1605  ereport(ERROR,
1606  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1607  errmsg("referenced relation \"%s\" is not a table or foreign table",
1608  RelationGetRelationName(tablerel))));
1609 
1610  /* We insist on same owner and schema */
1611  if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
1612  ereport(ERROR,
1613  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1614  errmsg("sequence must have same owner as table it is linked to")));
1615  if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
1616  ereport(ERROR,
1617  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1618  errmsg("sequence must be in same schema as table it is linked to")));
1619 
1620  /* Now, fetch the attribute number from the system cache */
1621  attnum = get_attnum(RelationGetRelid(tablerel), attrname);
1622  if (attnum == InvalidAttrNumber)
1623  ereport(ERROR,
1624  (errcode(ERRCODE_UNDEFINED_COLUMN),
1625  errmsg("column \"%s\" of relation \"%s\" does not exist",
1626  attrname, RelationGetRelationName(tablerel))));
1627  }
1628 
1629  /*
1630  * OK, we are ready to update pg_depend. First remove any existing AUTO
1631  * dependencies for the sequence, then optionally add a new one.
1632  */
1634 
1635  if (tablerel)
1636  {
1637  ObjectAddress refobject,
1638  depobject;
1639 
1640  refobject.classId = RelationRelationId;
1641  refobject.objectId = RelationGetRelid(tablerel);
1642  refobject.objectSubId = attnum;
1643  depobject.classId = RelationRelationId;
1644  depobject.objectId = RelationGetRelid(seqrel);
1645  depobject.objectSubId = 0;
1646  recordDependencyOn(&depobject, &refobject, DEPENDENCY_AUTO);
1647  }
1648 
1649  /* Done, but hold lock until commit */
1650  if (tablerel)
1651  relation_close(tablerel, NoLock);
1652 }
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1195
int errhint(const char *fmt,...)
Definition: elog.c:987
#define RelationRelationId
Definition: pg_class.h:29
List * list_truncate(List *list, int new_size)
Definition: list.c:350
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2857
Form_pg_class rd_rel
Definition: rel.h:113
static ListCell * list_tail(List *l)
Definition: pg_list.h:83
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:166
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void markSequenceUnowned(Oid seqId)
Definition: pg_depend.c:550
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:160
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:413
#define RelationGetNamespace(relation)
Definition: rel.h:440
static Form_pg_sequence_data read_seq_tuple ( Relation  rel,
Buffer buf,
HeapTuple  seqdatatuple 
)
static

Definition at line 1167 of file sequence.c.

References Assert, 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(), and ResetSequence().

1168 {
1169  Page page;
1170  ItemId lp;
1171  sequence_magic *sm;
1173 
1174  *buf = ReadBuffer(rel, 0);
1176 
1177  page = BufferGetPage(*buf);
1178  sm = (sequence_magic *) PageGetSpecialPointer(page);
1179 
1180  if (sm->magic != SEQ_MAGIC)
1181  elog(ERROR, "bad magic number in sequence \"%s\": %08X",
1182  RelationGetRelationName(rel), sm->magic);
1183 
1184  lp = PageGetItemId(page, FirstOffsetNumber);
1185  Assert(ItemIdIsNormal(lp));
1186 
1187  /* Note we currently only bother to set these two fields of *seqdatatuple */
1188  seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1189  seqdatatuple->t_len = ItemIdGetLength(lp);
1190 
1191  /*
1192  * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1193  * a sequence, which would leave a non-frozen XID in the sequence tuple's
1194  * xmax, which eventually leads to clog access failures or worse. If we
1195  * see this has happened, clean up after it. We treat this like a hint
1196  * bit update, ie, don't bother to WAL-log it, since we can certainly do
1197  * this again if the update gets lost.
1198  */
1199  Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
1201  {
1203  seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
1204  seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
1205  MarkBufferDirtyHint(*buf, true);
1206  }
1207 
1208  seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
1209 
1210  return seq;
1211 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SEQ_MAGIC
Definition: sequence.c:59
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3362
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
uint32 t_len
Definition: htup.h:64
static char * buf
Definition: pg_test_fsync.c:65
#define FirstOffsetNumber
Definition: off.h:27
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define Assert(condition)
Definition: c.h:671
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint32 magic
Definition: sequence.c:63
#define PageGetSpecialPointer(page)
Definition: bufpage.h:323
#define elog
Definition: elog.h:219
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
Pointer Page
Definition: bufpage.h:74
void ResetSequence ( Oid  seq_relid)

Definition at line 263 of file sequence.c.

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

264 {
265  Relation seq_rel;
266  SeqTable elm;
268  Buffer buf;
269  HeapTupleData seqdatatuple;
270  HeapTuple tuple;
271  HeapTuple pgstuple;
272  Form_pg_sequence pgsform;
273  int64 startv;
274 
275  /*
276  * Read the old sequence. This does a bit more work than really
277  * necessary, but it's simple, and we do want to double-check that it's
278  * indeed a sequence.
279  */
280  init_sequence(seq_relid, &elm, &seq_rel);
281  (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
282 
283  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
284  if (!HeapTupleIsValid(pgstuple))
285  elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
286  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
287  startv = pgsform->seqstart;
288  ReleaseSysCache(pgstuple);
289 
290  /*
291  * Copy the existing sequence tuple.
292  */
293  tuple = heap_copytuple(&seqdatatuple);
294 
295  /* Now we're done with the old page */
296  UnlockReleaseBuffer(buf);
297 
298  /*
299  * Modify the copied tuple to execute the restart (compare the RESTART
300  * action in AlterSequence)
301  */
302  seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
303  seq->last_value = startv;
304  seq->is_called = false;
305  seq->log_cnt = 0;
306 
307  /*
308  * Create a new storage file for the sequence. We want to keep the
309  * sequence's relfrozenxid at 0, since it won't contain any unfrozen XIDs.
310  * Same with relminmxid, since a sequence will never contain multixacts.
311  */
312  RelationSetNewRelfilenode(seq_rel, seq_rel->rd_rel->relpersistence,
314 
315  /*
316  * Insert the modified tuple into the new storage file.
317  */
318  fill_seq_with_data(seq_rel, tuple);
319 
320  /* Clear local cache so that we don't think we have cached numbers */
321  /* Note that we do not change the currval() state */
322  elm->cached = elm->last;
323 
324  relation_close(seq_rel, NoLock);
325 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
int64 cached
Definition: sequence.c:79
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3414
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
Form_pg_class rd_rel
Definition: rel.h:113
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:65
#define InvalidTransactionId
Definition: transam.h:31
int64 last
Definition: sequence.c:78
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1167
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define InvalidMultiXactId
Definition: multixact.h:23
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1100
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:331
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
void ResetSequenceCaches ( void  )

Definition at line 1807 of file sequence.c.

References hash_destroy(), and NULL.

Referenced by DiscardAll(), and DiscardCommand().

1808 {
1809  if (seqhashtab)
1810  {
1812  seqhashtab = NULL;
1813  }
1814 
1815  last_used_seq = NULL;
1816 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
static HTAB * seqhashtab
Definition: sequence.c:87
#define NULL
Definition: c.h:226
static SeqTableData * last_used_seq
Definition: sequence.c:93
void seq_mask ( char *  page,
BlockNumber  blkno 
)

Definition at line 1822 of file sequence.c.

References mask_page_lsn(), and mask_unused_space().

1823 {
1824  mask_page_lsn(page);
1825 
1826  mask_unused_space(page);
1827 }
void mask_unused_space(Page page)
Definition: bufmask.c:69
void mask_page_lsn(Page page)
Definition: bufmask.c:30
void seq_redo ( XLogReaderState record)

Definition at line 1754 of file sequence.c.

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.

1755 {
1756  XLogRecPtr lsn = record->EndRecPtr;
1757  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1758  Buffer buffer;
1759  Page page;
1760  Page localpage;
1761  char *item;
1762  Size itemsz;
1763  xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1764  sequence_magic *sm;
1765 
1766  if (info != XLOG_SEQ_LOG)
1767  elog(PANIC, "seq_redo: unknown op code %u", info);
1768 
1769  buffer = XLogInitBufferForRedo(record, 0);
1770  page = (Page) BufferGetPage(buffer);
1771 
1772  /*
1773  * We always reinit the page. However, since this WAL record type is also
1774  * used for updating sequences, it's possible that a hot-standby backend
1775  * is examining the page concurrently; so we mustn't transiently trash the
1776  * buffer. The solution is to build the correct new page contents in
1777  * local workspace and then memcpy into the buffer. Then only bytes that
1778  * are supposed to change will change, even transiently. We must palloc
1779  * the local page for alignment reasons.
1780  */
1781  localpage = (Page) palloc(BufferGetPageSize(buffer));
1782 
1783  PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1784  sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1785  sm->magic = SEQ_MAGIC;
1786 
1787  item = (char *) xlrec + sizeof(xl_seq_rec);
1788  itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1789 
1790  if (PageAddItem(localpage, (Item) item, itemsz,
1791  FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1792  elog(PANIC, "seq_redo: failed to add item to page");
1793 
1794  PageSetLSN(localpage, lsn);
1795 
1796  memcpy(page, localpage, BufferGetPageSize(buffer));
1797  MarkBufferDirty(buffer);
1798  UnlockReleaseBuffer(buffer);
1799 
1800  pfree(localpage);
1801 }
#define SEQ_MAGIC
Definition: sequence.c:59
struct xl_seq_rec xl_seq_rec
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
unsigned char uint8
Definition: c.h:263
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:413
#define PANIC
Definition: elog.h:53
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
void pfree(void *pointer)
Definition: mcxt.c:992
#define XLogRecGetData(decoder)
Definition: xlogreader.h:202
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:203
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:300
#define FirstOffsetNumber
Definition: off.h:27
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:198
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define InvalidOffsetNumber
Definition: off.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
uint32 magic
Definition: sequence.c:63
size_t Size
Definition: c.h:353
#define PageGetSpecialPointer(page)
Definition: bufpage.h:323
void * palloc(Size size)
Definition: mcxt.c:891
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
Datum setval3_oid ( PG_FUNCTION_ARGS  )

Definition at line 1026 of file sequence.c.

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

1027 {
1028  Oid relid = PG_GETARG_OID(0);
1029  int64 next = PG_GETARG_INT64(1);
1030  bool iscalled = PG_GETARG_BOOL(2);
1031 
1032  do_setval(relid, next, iscalled);
1033 
1034  PG_RETURN_INT64(next);
1035 }
static int32 next
Definition: blutils.c:210
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:898
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
Datum setval_oid ( PG_FUNCTION_ARGS  )

Definition at line 1011 of file sequence.c.

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

1012 {
1013  Oid relid = PG_GETARG_OID(0);
1014  int64 next = PG_GETARG_INT64(1);
1015 
1016  do_setval(relid, next, true);
1017 
1018  PG_RETURN_INT64(next);
1019 }
static int32 next
Definition: blutils.c:210
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:898
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238

Variable Documentation

SeqTableData* last_used_seq = NULL
static

Definition at line 93 of file sequence.c.

HTAB* seqhashtab = NULL
static

Definition at line 87 of file sequence.c.