PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
sequence.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * sequence.c
4  * PostgreSQL sequences support code.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/commands/sequence.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/bufmask.h"
18 #include "access/htup_details.h"
19 #include "access/multixact.h"
20 #include "access/transam.h"
21 #include "access/xact.h"
22 #include "access/xlog.h"
23 #include "access/xloginsert.h"
24 #include "access/xlogutils.h"
25 #include "catalog/dependency.h"
26 #include "catalog/indexing.h"
27 #include "catalog/namespace.h"
28 #include "catalog/objectaccess.h"
29 #include "catalog/pg_sequence.h"
30 #include "catalog/pg_type.h"
31 #include "commands/defrem.h"
32 #include "commands/sequence.h"
33 #include "commands/tablecmds.h"
34 #include "funcapi.h"
35 #include "miscadmin.h"
36 #include "nodes/makefuncs.h"
37 #include "parser/parse_type.h"
38 #include "storage/lmgr.h"
39 #include "storage/proc.h"
40 #include "storage/smgr.h"
41 #include "utils/acl.h"
42 #include "utils/builtins.h"
43 #include "utils/lsyscache.h"
44 #include "utils/resowner.h"
45 #include "utils/syscache.h"
46 #include "utils/varlena.h"
47 
48 
49 /*
50  * We don't want to log each fetching of a value from a sequence,
51  * so we pre-log a few fetches in advance. In the event of
52  * crash we can lose (skip over) as many values as we pre-logged.
53  */
54 #define SEQ_LOG_VALS 32
55 
56 /*
57  * The "special area" of a sequence's buffer page looks like this.
58  */
59 #define SEQ_MAGIC 0x1717
60 
61 typedef struct sequence_magic
62 {
65 
66 /*
67  * We store a SeqTable item for every sequence we have touched in the current
68  * session. This is needed to hold onto nextval/currval state. (We can't
69  * rely on the relcache, since it's only, well, a cache, and may decide to
70  * discard entries.)
71  */
72 typedef struct SeqTableData
73 {
74  Oid relid; /* pg_class OID of this sequence (hash key) */
75  Oid filenode; /* last seen relfilenode of this sequence */
76  LocalTransactionId lxid; /* xact in which we last did a seq op */
77  bool last_valid; /* do we have a valid "last" value? */
78  int64 last; /* value last returned by nextval */
79  int64 cached; /* last value already cached for nextval */
80  /* if last != cached, we have not used up all the cached values */
81  int64 increment; /* copy of sequence's increment field */
82  /* note that increment is zero until we first do nextval_internal() */
83 } SeqTableData;
84 
86 
87 static HTAB *seqhashtab = NULL; /* hash table for SeqTable items */
88 
89 /*
90  * last_used_seq is updated by nextval() to point to the last used
91  * sequence.
92  */
94 
95 static void fill_seq_with_data(Relation rel, HeapTuple tuple);
97 static void create_seq_hashtable(void);
98 static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
100  Buffer *buf, HeapTuple seqdatatuple);
102 static void init_params(ParseState *pstate, List *options, bool for_identity,
103  bool isInit,
104  Form_pg_sequence seqform,
105  bool *changed_seqform,
106  Form_pg_sequence_data seqdataform, List **owned_by);
107 static void do_setval(Oid relid, int64 next, bool iscalled);
108 static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity);
109 
110 
111 /*
112  * DefineSequence
113  * Creates a new sequence relation
114  */
117 {
118  FormData_pg_sequence seqform;
119  FormData_pg_sequence_data seqdataform;
120  bool changed_seqform = false; /* not used here */
121  List *owned_by;
122  CreateStmt *stmt = makeNode(CreateStmt);
123  Oid seqoid;
124  ObjectAddress address;
125  Relation rel;
126  HeapTuple tuple;
127  TupleDesc tupDesc;
129  bool null[SEQ_COL_LASTCOL];
130  Datum pgs_values[Natts_pg_sequence];
131  bool pgs_nulls[Natts_pg_sequence];
132  int i;
133 
134  /* Unlogged sequences are not implemented -- not clear if useful. */
136  ereport(ERROR,
137  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
138  errmsg("unlogged sequences are not supported")));
139 
140  /*
141  * If if_not_exists was given and a relation with the same name already
142  * exists, bail out. (Note: we needn't check this when not if_not_exists,
143  * because DefineRelation will complain anyway.)
144  */
145  if (seq->if_not_exists)
146  {
148  if (OidIsValid(seqoid))
149  {
150  ereport(NOTICE,
151  (errcode(ERRCODE_DUPLICATE_TABLE),
152  errmsg("relation \"%s\" already exists, skipping",
153  seq->sequence->relname)));
154  return InvalidObjectAddress;
155  }
156  }
157 
158  /* Check and set all option values */
159  init_params(pstate, seq->options, seq->for_identity, true, &seqform, &changed_seqform, &seqdataform, &owned_by);
160 
161  /*
162  * Create relation (and fill value[] and null[] for the tuple)
163  */
164  stmt->tableElts = NIL;
165  for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
166  {
167  ColumnDef *coldef = makeNode(ColumnDef);
168 
169  coldef->inhcount = 0;
170  coldef->is_local = true;
171  coldef->is_not_null = true;
172  coldef->is_from_type = false;
173  coldef->is_from_parent = false;
174  coldef->storage = 0;
175  coldef->raw_default = NULL;
176  coldef->cooked_default = NULL;
177  coldef->collClause = NULL;
178  coldef->collOid = InvalidOid;
179  coldef->constraints = NIL;
180  coldef->location = -1;
181 
182  null[i - 1] = false;
183 
184  switch (i)
185  {
186  case SEQ_COL_LASTVAL:
187  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
188  coldef->colname = "last_value";
189  value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
190  break;
191  case SEQ_COL_LOG:
192  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
193  coldef->colname = "log_cnt";
194  value[i - 1] = Int64GetDatum((int64) 0);
195  break;
196  case SEQ_COL_CALLED:
197  coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
198  coldef->colname = "is_called";
199  value[i - 1] = BoolGetDatum(false);
200  break;
201  }
202  stmt->tableElts = lappend(stmt->tableElts, coldef);
203  }
204 
205  stmt->relation = seq->sequence;
206  stmt->inhRelations = NIL;
207  stmt->constraints = NIL;
208  stmt->options = NIL;
209  stmt->oncommit = ONCOMMIT_NOOP;
210  stmt->tablespacename = NULL;
211  stmt->if_not_exists = seq->if_not_exists;
212 
213  address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
214  seqoid = address.objectId;
215  Assert(seqoid != InvalidOid);
216 
217  rel = heap_open(seqoid, AccessExclusiveLock);
218  tupDesc = RelationGetDescr(rel);
219 
220  /* now initialize the sequence's data */
221  tuple = heap_form_tuple(tupDesc, value, null);
222  fill_seq_with_data(rel, tuple);
223 
224  /* process OWNED BY if given */
225  if (owned_by)
226  process_owned_by(rel, owned_by, seq->for_identity);
227 
228  heap_close(rel, NoLock);
229 
230  /* fill in pg_sequence */
232  tupDesc = RelationGetDescr(rel);
233 
234  memset(pgs_nulls, 0, sizeof(pgs_nulls));
235 
236  pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
237  pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
238  pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
239  pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
240  pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
241  pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
242  pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
243  pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
244 
245  tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
246  CatalogTupleInsert(rel, tuple);
247 
248  heap_freetuple(tuple);
250 
251  return address;
252 }
253 
254 /*
255  * Reset a sequence to its initial value.
256  *
257  * The change is made transactionally, so that on failure of the current
258  * transaction, the sequence will be restored to its previous state.
259  * We do that by creating a whole new relfilenode for the sequence; so this
260  * works much like the rewriting forms of ALTER TABLE.
261  *
262  * Caller is assumed to have acquired AccessExclusiveLock on the sequence,
263  * which must not be released until end of transaction. Caller is also
264  * responsible for permissions checking.
265  */
266 void
267 ResetSequence(Oid seq_relid)
268 {
269  Relation seq_rel;
270  SeqTable elm;
272  Buffer buf;
273  HeapTupleData seqdatatuple;
274  HeapTuple tuple;
275  HeapTuple pgstuple;
276  Form_pg_sequence pgsform;
277  int64 startv;
278 
279  /*
280  * Read the old sequence. This does a bit more work than really
281  * necessary, but it's simple, and we do want to double-check that it's
282  * indeed a sequence.
283  */
284  init_sequence(seq_relid, &elm, &seq_rel);
285  (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
286 
287  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
288  if (!HeapTupleIsValid(pgstuple))
289  elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
290  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
291  startv = pgsform->seqstart;
292  ReleaseSysCache(pgstuple);
293 
294  /*
295  * Copy the existing sequence tuple.
296  */
297  tuple = heap_copytuple(&seqdatatuple);
298 
299  /* Now we're done with the old page */
300  UnlockReleaseBuffer(buf);
301 
302  /*
303  * Modify the copied tuple to execute the restart (compare the RESTART
304  * action in AlterSequence)
305  */
306  seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
307  seq->last_value = startv;
308  seq->is_called = false;
309  seq->log_cnt = 0;
310 
311  /*
312  * Create a new storage file for the sequence. We want to keep the
313  * sequence's relfrozenxid at 0, since it won't contain any unfrozen XIDs.
314  * Same with relminmxid, since a sequence will never contain multixacts.
315  */
316  RelationSetNewRelfilenode(seq_rel, seq_rel->rd_rel->relpersistence,
318 
319  /*
320  * Insert the modified tuple into the new storage file.
321  */
322  fill_seq_with_data(seq_rel, tuple);
323 
324  /* Clear local cache so that we don't think we have cached numbers */
325  /* Note that we do not change the currval() state */
326  elm->cached = elm->last;
327 
328  relation_close(seq_rel, NoLock);
329 }
330 
331 /*
332  * Initialize a sequence's relation with the specified tuple as content
333  */
334 static void
336 {
337  Buffer buf;
338  Page page;
339  sequence_magic *sm;
340  OffsetNumber offnum;
341 
342  /* Initialize first page of relation with special magic number */
343 
344  buf = ReadBuffer(rel, P_NEW);
345  Assert(BufferGetBlockNumber(buf) == 0);
346 
347  page = BufferGetPage(buf);
348 
349  PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
350  sm = (sequence_magic *) PageGetSpecialPointer(page);
351  sm->magic = SEQ_MAGIC;
352 
353  /* Now insert sequence tuple */
354 
356 
357  /*
358  * Since VACUUM does not process sequences, we have to force the tuple to
359  * have xmin = FrozenTransactionId now. Otherwise it would become
360  * invisible to SELECTs after 2G transactions. It is okay to do this
361  * because if the current transaction aborts, no other xact will ever
362  * examine the sequence tuple anyway.
363  */
370 
371  /* check the comment above nextval_internal()'s equivalent call. */
372  if (RelationNeedsWAL(rel))
374 
376 
377  MarkBufferDirty(buf);
378 
379  offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
380  InvalidOffsetNumber, false, false);
381  if (offnum != FirstOffsetNumber)
382  elog(ERROR, "failed to add sequence tuple to page");
383 
384  /* XLOG stuff */
385  if (RelationNeedsWAL(rel))
386  {
387  xl_seq_rec xlrec;
388  XLogRecPtr recptr;
389 
390  XLogBeginInsert();
392 
393  xlrec.node = rel->rd_node;
394 
395  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
396  XLogRegisterData((char *) tuple->t_data, tuple->t_len);
397 
398  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
399 
400  PageSetLSN(page, recptr);
401  }
402 
404 
405  UnlockReleaseBuffer(buf);
406 }
407 
408 /*
409  * AlterSequence
410  *
411  * Modify the definition of a sequence relation
412  */
415 {
416  Oid relid;
417  SeqTable elm;
418  Relation seqrel;
419  Buffer buf;
420  HeapTupleData seqdatatuple;
421  Form_pg_sequence seqform;
422  Form_pg_sequence_data seqdata;
423  FormData_pg_sequence_data newseqdata;
424  bool changed_seqform = false;
425  List *owned_by;
426  ObjectAddress address;
427  Relation rel;
428  HeapTuple tuple;
429 
430  /* Open and lock sequence. */
431  relid = RangeVarGetRelid(stmt->sequence,
433  stmt->missing_ok);
434  if (relid == InvalidOid)
435  {
436  ereport(NOTICE,
437  (errmsg("relation \"%s\" does not exist, skipping",
438  stmt->sequence->relname)));
439  return InvalidObjectAddress;
440  }
441 
442  init_sequence(relid, &elm, &seqrel);
443 
444  /* allow ALTER to sequence owner only */
445  if (!pg_class_ownercheck(relid, GetUserId()))
447  stmt->sequence->relname);
448 
451  ObjectIdGetDatum(relid));
452  if (!HeapTupleIsValid(tuple))
453  elog(ERROR, "cache lookup failed for sequence %u",
454  relid);
455 
456  seqform = (Form_pg_sequence) GETSTRUCT(tuple);
457 
458  /* lock page's buffer and read tuple into new sequence structure */
459  seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
460 
461  /* Copy old sequence data into workspace */
462  memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
463 
464  /* Check and set new values */
465  init_params(pstate, stmt->options, stmt->for_identity, false, seqform, &changed_seqform, &newseqdata, &owned_by);
466 
467  /* Clear local cache so that we don't think we have cached numbers */
468  /* Note that we do not change the currval() state */
469  elm->cached = elm->last;
470 
471  /* check the comment above nextval_internal()'s equivalent call. */
472  if (RelationNeedsWAL(seqrel))
474 
475  /* Now okay to update the on-disk tuple */
477 
478  memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
479 
480  MarkBufferDirty(buf);
481 
482  /* XLOG stuff */
483  if (RelationNeedsWAL(seqrel))
484  {
485  xl_seq_rec xlrec;
486  XLogRecPtr recptr;
487  Page page = BufferGetPage(buf);
488 
489  XLogBeginInsert();
491 
492  xlrec.node = seqrel->rd_node;
493  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
494 
495  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
496 
497  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
498 
499  PageSetLSN(page, recptr);
500  }
501 
503 
504  UnlockReleaseBuffer(buf);
505 
506  /* process OWNED BY if given */
507  if (owned_by)
508  process_owned_by(seqrel, owned_by, stmt->for_identity);
509 
511 
512  ObjectAddressSet(address, RelationRelationId, relid);
513 
514  if (changed_seqform)
515  CatalogTupleUpdate(rel, &tuple->t_self, tuple);
517 
518  relation_close(seqrel, NoLock);
519 
520  return address;
521 }
522 
523 void
525 {
526  Relation rel;
527  HeapTuple tuple;
528 
530 
531  tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
532  if (!HeapTupleIsValid(tuple))
533  elog(ERROR, "cache lookup failed for sequence %u", relid);
534 
535  CatalogTupleDelete(rel, &tuple->t_self);
536 
537  ReleaseSysCache(tuple);
539 }
540 
541 /*
542  * Note: nextval with a text argument is no longer exported as a pg_proc
543  * entry, but we keep it around to ease porting of C code that may have
544  * called the function directly.
545  */
546 Datum
548 {
549  text *seqin = PG_GETARG_TEXT_PP(0);
550  RangeVar *sequence;
551  Oid relid;
552 
554 
555  /*
556  * XXX: This is not safe in the presence of concurrent DDL, but acquiring
557  * a lock here is more expensive than letting nextval_internal do it,
558  * since the latter maintains a cache that keeps us from hitting the lock
559  * manager more than once per transaction. It's not clear whether the
560  * performance penalty is material in practice, but for now, we do it this
561  * way.
562  */
563  relid = RangeVarGetRelid(sequence, NoLock, false);
564 
565  PG_RETURN_INT64(nextval_internal(relid, true));
566 }
567 
568 Datum
570 {
571  Oid relid = PG_GETARG_OID(0);
572 
573  PG_RETURN_INT64(nextval_internal(relid, true));
574 }
575 
576 int64
578 {
579  SeqTable elm;
580  Relation seqrel;
581  Buffer buf;
582  Page page;
583  HeapTuple pgstuple;
584  Form_pg_sequence pgsform;
585  HeapTupleData seqdatatuple;
587  int64 incby,
588  maxv,
589  minv,
590  cache,
591  log,
592  fetch,
593  last;
594  int64 result,
595  next,
596  rescnt = 0;
597  bool cycle;
598  bool logit = false;
599 
600  /* open and lock sequence */
601  init_sequence(relid, &elm, &seqrel);
602 
603  if (check_permissions &&
606  ereport(ERROR,
607  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
608  errmsg("permission denied for sequence %s",
609  RelationGetRelationName(seqrel))));
610 
611  /* read-only transactions may only modify temp sequences */
612  if (!seqrel->rd_islocaltemp)
613  PreventCommandIfReadOnly("nextval()");
614 
615  /*
616  * Forbid this during parallel operation because, to make it work, the
617  * cooperating backends would need to share the backend-local cached
618  * sequence information. Currently, we don't support that.
619  */
620  PreventCommandIfParallelMode("nextval()");
621 
622  if (elm->last != elm->cached) /* some numbers were cached */
623  {
624  Assert(elm->last_valid);
625  Assert(elm->increment != 0);
626  elm->last += elm->increment;
627  relation_close(seqrel, NoLock);
628  last_used_seq = elm;
629  return elm->last;
630  }
631 
632  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
633  if (!HeapTupleIsValid(pgstuple))
634  elog(ERROR, "cache lookup failed for sequence %u", relid);
635  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
636  incby = pgsform->seqincrement;
637  maxv = pgsform->seqmax;
638  minv = pgsform->seqmin;
639  cache = pgsform->seqcache;
640  cycle = pgsform->seqcycle;
641  ReleaseSysCache(pgstuple);
642 
643  /* lock page' buffer and read tuple */
644  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
645  page = BufferGetPage(buf);
646 
647  elm->increment = incby;
648  last = next = result = seq->last_value;
649  fetch = cache;
650  log = seq->log_cnt;
651 
652  if (!seq->is_called)
653  {
654  rescnt++; /* return last_value if not is_called */
655  fetch--;
656  }
657 
658  /*
659  * Decide whether we should emit a WAL log record. If so, force up the
660  * fetch count to grab SEQ_LOG_VALS more values than we actually need to
661  * cache. (These will then be usable without logging.)
662  *
663  * If this is the first nextval after a checkpoint, we must force a new
664  * WAL record to be written anyway, else replay starting from the
665  * checkpoint would fail to advance the sequence past the logged values.
666  * In this case we may as well fetch extra values.
667  */
668  if (log < fetch || !seq->is_called)
669  {
670  /* forced log to satisfy local demand for values */
671  fetch = log = fetch + SEQ_LOG_VALS;
672  logit = true;
673  }
674  else
675  {
676  XLogRecPtr redoptr = GetRedoRecPtr();
677 
678  if (PageGetLSN(page) <= redoptr)
679  {
680  /* last update of seq was before checkpoint */
681  fetch = log = fetch + SEQ_LOG_VALS;
682  logit = true;
683  }
684  }
685 
686  while (fetch) /* try to fetch cache [+ log ] numbers */
687  {
688  /*
689  * Check MAXVALUE for ascending sequences and MINVALUE for descending
690  * sequences
691  */
692  if (incby > 0)
693  {
694  /* ascending sequence */
695  if ((maxv >= 0 && next > maxv - incby) ||
696  (maxv < 0 && next + incby > maxv))
697  {
698  if (rescnt > 0)
699  break; /* stop fetching */
700  if (!cycle)
701  {
702  char buf[100];
703 
704  snprintf(buf, sizeof(buf), INT64_FORMAT, maxv);
705  ereport(ERROR,
706  (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
707  errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",
708  RelationGetRelationName(seqrel), buf)));
709  }
710  next = minv;
711  }
712  else
713  next += incby;
714  }
715  else
716  {
717  /* descending sequence */
718  if ((minv < 0 && next < minv - incby) ||
719  (minv >= 0 && next + incby < minv))
720  {
721  if (rescnt > 0)
722  break; /* stop fetching */
723  if (!cycle)
724  {
725  char buf[100];
726 
727  snprintf(buf, sizeof(buf), INT64_FORMAT, minv);
728  ereport(ERROR,
729  (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
730  errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",
731  RelationGetRelationName(seqrel), buf)));
732  }
733  next = maxv;
734  }
735  else
736  next += incby;
737  }
738  fetch--;
739  if (rescnt < cache)
740  {
741  log--;
742  rescnt++;
743  last = next;
744  if (rescnt == 1) /* if it's first result - */
745  result = next; /* it's what to return */
746  }
747  }
748 
749  log -= fetch; /* adjust for any unfetched numbers */
750  Assert(log >= 0);
751 
752  /* save info in local cache */
753  elm->last = result; /* last returned number */
754  elm->cached = last; /* last fetched number */
755  elm->last_valid = true;
756 
757  last_used_seq = elm;
758 
759  /*
760  * If something needs to be WAL logged, acquire an xid, so this
761  * transaction's commit will trigger a WAL flush and wait for syncrep.
762  * It's sufficient to ensure the toplevel transaction has an xid, no need
763  * to assign xids subxacts, that'll already trigger an appropriate wait.
764  * (Have to do that here, so we're outside the critical section)
765  */
766  if (logit && RelationNeedsWAL(seqrel))
768 
769  /* ready to change the on-disk (or really, in-buffer) tuple */
771 
772  /*
773  * We must mark the buffer dirty before doing XLogInsert(); see notes in
774  * SyncOneBuffer(). However, we don't apply the desired changes just yet.
775  * This looks like a violation of the buffer update protocol, but it is in
776  * fact safe because we hold exclusive lock on the buffer. Any other
777  * process, including a checkpoint, that tries to examine the buffer
778  * contents will block until we release the lock, and then will see the
779  * final state that we install below.
780  */
781  MarkBufferDirty(buf);
782 
783  /* XLOG stuff */
784  if (logit && RelationNeedsWAL(seqrel))
785  {
786  xl_seq_rec xlrec;
787  XLogRecPtr recptr;
788 
789  /*
790  * We don't log the current state of the tuple, but rather the state
791  * as it would appear after "log" more fetches. This lets us skip
792  * that many future WAL records, at the cost that we lose those
793  * sequence values if we crash.
794  */
795  XLogBeginInsert();
797 
798  /* set values that will be saved in xlog */
799  seq->last_value = next;
800  seq->is_called = true;
801  seq->log_cnt = 0;
802 
803  xlrec.node = seqrel->rd_node;
804 
805  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
806  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
807 
808  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
809 
810  PageSetLSN(page, recptr);
811  }
812 
813  /* Now update sequence tuple to the intended final state */
814  seq->last_value = last; /* last fetched number */
815  seq->is_called = true;
816  seq->log_cnt = log; /* how much is logged */
817 
819 
820  UnlockReleaseBuffer(buf);
821 
822  relation_close(seqrel, NoLock);
823 
824  return result;
825 }
826 
827 Datum
829 {
830  Oid relid = PG_GETARG_OID(0);
831  int64 result;
832  SeqTable elm;
833  Relation seqrel;
834 
835  /* open and lock sequence */
836  init_sequence(relid, &elm, &seqrel);
837 
838  if (pg_class_aclcheck(elm->relid, GetUserId(),
840  ereport(ERROR,
841  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
842  errmsg("permission denied for sequence %s",
843  RelationGetRelationName(seqrel))));
844 
845  if (!elm->last_valid)
846  ereport(ERROR,
847  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
848  errmsg("currval of sequence \"%s\" is not yet defined in this session",
849  RelationGetRelationName(seqrel))));
850 
851  result = elm->last;
852 
853  relation_close(seqrel, NoLock);
854 
855  PG_RETURN_INT64(result);
856 }
857 
858 Datum
860 {
861  Relation seqrel;
862  int64 result;
863 
864  if (last_used_seq == NULL)
865  ereport(ERROR,
866  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
867  errmsg("lastval is not yet defined in this session")));
868 
869  /* Someone may have dropped the sequence since the last nextval() */
870  if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(last_used_seq->relid)))
871  ereport(ERROR,
872  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
873  errmsg("lastval is not yet defined in this session")));
874 
875  seqrel = lock_and_open_sequence(last_used_seq);
876 
877  /* nextval() must have already been called for this sequence */
878  Assert(last_used_seq->last_valid);
879 
880  if (pg_class_aclcheck(last_used_seq->relid, GetUserId(),
882  ereport(ERROR,
883  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
884  errmsg("permission denied for sequence %s",
885  RelationGetRelationName(seqrel))));
886 
887  result = last_used_seq->last;
888  relation_close(seqrel, NoLock);
889 
890  PG_RETURN_INT64(result);
891 }
892 
893 /*
894  * Main internal procedure that handles 2 & 3 arg forms of SETVAL.
895  *
896  * Note that the 3 arg version (which sets the is_called flag) is
897  * only for use in pg_dump, and setting the is_called flag may not
898  * work if multiple users are attached to the database and referencing
899  * the sequence (unlikely if pg_dump is restoring it).
900  *
901  * It is necessary to have the 3 arg version so that pg_dump can
902  * restore the state of a sequence exactly during data-only restores -
903  * it is the only way to clear the is_called flag in an existing
904  * sequence.
905  */
906 static void
907 do_setval(Oid relid, int64 next, bool iscalled)
908 {
909  SeqTable elm;
910  Relation seqrel;
911  Buffer buf;
912  HeapTupleData seqdatatuple;
914  HeapTuple pgstuple;
915  Form_pg_sequence pgsform;
916  int64 maxv,
917  minv;
918 
919  /* open and lock sequence */
920  init_sequence(relid, &elm, &seqrel);
921 
923  ereport(ERROR,
924  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
925  errmsg("permission denied for sequence %s",
926  RelationGetRelationName(seqrel))));
927 
928  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
929  if (!HeapTupleIsValid(pgstuple))
930  elog(ERROR, "cache lookup failed for sequence %u", relid);
931  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
932  maxv = pgsform->seqmax;
933  minv = pgsform->seqmin;
934  ReleaseSysCache(pgstuple);
935 
936  /* read-only transactions may only modify temp sequences */
937  if (!seqrel->rd_islocaltemp)
938  PreventCommandIfReadOnly("setval()");
939 
940  /*
941  * Forbid this during parallel operation because, to make it work, the
942  * cooperating backends would need to share the backend-local cached
943  * sequence information. Currently, we don't support that.
944  */
945  PreventCommandIfParallelMode("setval()");
946 
947  /* lock page' buffer and read tuple */
948  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
949 
950  if ((next < minv) || (next > maxv))
951  {
952  char bufv[100],
953  bufm[100],
954  bufx[100];
955 
956  snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
957  snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
958  snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
959  ereport(ERROR,
960  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
961  errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
962  bufv, RelationGetRelationName(seqrel),
963  bufm, bufx)));
964  }
965 
966  /* Set the currval() state only if iscalled = true */
967  if (iscalled)
968  {
969  elm->last = next; /* last returned number */
970  elm->last_valid = true;
971  }
972 
973  /* In any case, forget any future cached numbers */
974  elm->cached = elm->last;
975 
976  /* check the comment above nextval_internal()'s equivalent call. */
977  if (RelationNeedsWAL(seqrel))
979 
980  /* ready to change the on-disk (or really, in-buffer) tuple */
982 
983  seq->last_value = next; /* last fetched number */
984  seq->is_called = iscalled;
985  seq->log_cnt = 0;
986 
987  MarkBufferDirty(buf);
988 
989  /* XLOG stuff */
990  if (RelationNeedsWAL(seqrel))
991  {
992  xl_seq_rec xlrec;
993  XLogRecPtr recptr;
994  Page page = BufferGetPage(buf);
995 
996  XLogBeginInsert();
998 
999  xlrec.node = seqrel->rd_node;
1000  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
1001  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
1002 
1003  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
1004 
1005  PageSetLSN(page, recptr);
1006  }
1007 
1008  END_CRIT_SECTION();
1009 
1010  UnlockReleaseBuffer(buf);
1011 
1012  relation_close(seqrel, NoLock);
1013 }
1014 
1015 /*
1016  * Implement the 2 arg setval procedure.
1017  * See do_setval for discussion.
1018  */
1019 Datum
1021 {
1022  Oid relid = PG_GETARG_OID(0);
1023  int64 next = PG_GETARG_INT64(1);
1024 
1025  do_setval(relid, next, true);
1026 
1027  PG_RETURN_INT64(next);
1028 }
1029 
1030 /*
1031  * Implement the 3 arg setval procedure.
1032  * See do_setval for discussion.
1033  */
1034 Datum
1036 {
1037  Oid relid = PG_GETARG_OID(0);
1038  int64 next = PG_GETARG_INT64(1);
1039  bool iscalled = PG_GETARG_BOOL(2);
1040 
1041  do_setval(relid, next, iscalled);
1042 
1043  PG_RETURN_INT64(next);
1044 }
1045 
1046 
1047 /*
1048  * Open the sequence and acquire lock if needed
1049  *
1050  * If we haven't touched the sequence already in this transaction,
1051  * we need to acquire a lock. We arrange for the lock to
1052  * be owned by the top transaction, so that we don't need to do it
1053  * more than once per xact.
1054  */
1055 static Relation
1057 {
1058  LocalTransactionId thislxid = MyProc->lxid;
1059 
1060  /* Get the lock if not already held in this xact */
1061  if (seq->lxid != thislxid)
1062  {
1063  ResourceOwner currentOwner;
1064 
1065  currentOwner = CurrentResourceOwner;
1066  PG_TRY();
1067  {
1070  }
1071  PG_CATCH();
1072  {
1073  /* Ensure CurrentResourceOwner is restored on error */
1074  CurrentResourceOwner = currentOwner;
1075  PG_RE_THROW();
1076  }
1077  PG_END_TRY();
1078  CurrentResourceOwner = currentOwner;
1079 
1080  /* Flag that we have a lock in the current xact */
1081  seq->lxid = thislxid;
1082  }
1083 
1084  /* We now know we have the lock, and can safely open the rel */
1085  return relation_open(seq->relid, NoLock);
1086 }
1087 
1088 /*
1089  * Creates the hash table for storing sequence data
1090  */
1091 static void
1093 {
1094  HASHCTL ctl;
1095 
1096  memset(&ctl, 0, sizeof(ctl));
1097  ctl.keysize = sizeof(Oid);
1098  ctl.entrysize = sizeof(SeqTableData);
1099 
1100  seqhashtab = hash_create("Sequence values", 16, &ctl,
1101  HASH_ELEM | HASH_BLOBS);
1102 }
1103 
1104 /*
1105  * Given a relation OID, open and lock the sequence. p_elm and p_rel are
1106  * output parameters.
1107  */
1108 static void
1109 init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
1110 {
1111  SeqTable elm;
1112  Relation seqrel;
1113  bool found;
1114 
1115  /* Find or create a hash table entry for this sequence */
1116  if (seqhashtab == NULL)
1118 
1119  elm = (SeqTable) hash_search(seqhashtab, &relid, HASH_ENTER, &found);
1120 
1121  /*
1122  * Initialize the new hash table entry if it did not exist already.
1123  *
1124  * NOTE: seqtable entries are stored for the life of a backend (unless
1125  * explicitly discarded with DISCARD). If the sequence itself is deleted
1126  * then the entry becomes wasted memory, but it's small enough that this
1127  * should not matter.
1128  */
1129  if (!found)
1130  {
1131  /* relid already filled in */
1132  elm->filenode = InvalidOid;
1134  elm->last_valid = false;
1135  elm->last = elm->cached = 0;
1136  }
1137 
1138  /*
1139  * Open the sequence relation.
1140  */
1141  seqrel = lock_and_open_sequence(elm);
1142 
1143  if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
1144  ereport(ERROR,
1145  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1146  errmsg("\"%s\" is not a sequence",
1147  RelationGetRelationName(seqrel))));
1148 
1149  /*
1150  * If the sequence has been transactionally replaced since we last saw it,
1151  * discard any cached-but-unissued values. We do not touch the currval()
1152  * state, however.
1153  */
1154  if (seqrel->rd_rel->relfilenode != elm->filenode)
1155  {
1156  elm->filenode = seqrel->rd_rel->relfilenode;
1157  elm->cached = elm->last;
1158  }
1159 
1160  /* Return results */
1161  *p_elm = elm;
1162  *p_rel = seqrel;
1163 }
1164 
1165 
1166 /*
1167  * Given an opened sequence relation, lock the page buffer and find the tuple
1168  *
1169  * *buf receives the reference to the pinned-and-ex-locked buffer
1170  * *seqdatatuple receives the reference to the sequence tuple proper
1171  * (this arg should point to a local variable of type HeapTupleData)
1172  *
1173  * Function's return value points to the data payload of the tuple
1174  */
1175 static Form_pg_sequence_data
1177 {
1178  Page page;
1179  ItemId lp;
1180  sequence_magic *sm;
1182 
1183  *buf = ReadBuffer(rel, 0);
1185 
1186  page = BufferGetPage(*buf);
1187  sm = (sequence_magic *) PageGetSpecialPointer(page);
1188 
1189  if (sm->magic != SEQ_MAGIC)
1190  elog(ERROR, "bad magic number in sequence \"%s\": %08X",
1191  RelationGetRelationName(rel), sm->magic);
1192 
1193  lp = PageGetItemId(page, FirstOffsetNumber);
1194  Assert(ItemIdIsNormal(lp));
1195 
1196  /* Note we currently only bother to set these two fields of *seqdatatuple */
1197  seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1198  seqdatatuple->t_len = ItemIdGetLength(lp);
1199 
1200  /*
1201  * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1202  * a sequence, which would leave a non-frozen XID in the sequence tuple's
1203  * xmax, which eventually leads to clog access failures or worse. If we
1204  * see this has happened, clean up after it. We treat this like a hint
1205  * bit update, ie, don't bother to WAL-log it, since we can certainly do
1206  * this again if the update gets lost.
1207  */
1208  Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
1210  {
1212  seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
1213  seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
1214  MarkBufferDirtyHint(*buf, true);
1215  }
1216 
1217  seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
1218 
1219  return seq;
1220 }
1221 
1222 /*
1223  * Check the sequence options list and return the appropriate lock level for
1224  * ALTER SEQUENCE.
1225  *
1226  * Most sequence option changes require a self-exclusive lock and should block
1227  * concurrent nextval() et al. But RESTART does not, because it's not
1228  * transactional. Also take a lower lock if no option at all is present.
1229  */
1230 static LOCKMODE
1232 {
1233  ListCell *option;
1234 
1235  foreach(option, options)
1236  {
1237  DefElem *defel = (DefElem *) lfirst(option);
1238 
1239  if (strcmp(defel->defname, "restart") != 0)
1240  return ShareRowExclusiveLock;
1241  }
1242 
1243  return RowExclusiveLock;
1244 }
1245 
1246 /*
1247  * init_params: process the options list of CREATE or ALTER SEQUENCE, and
1248  * store the values into appropriate fields of seqform, for changes that go
1249  * into the pg_sequence catalog, and seqdataform for changes to the sequence
1250  * relation itself. Set *changed_seqform to true if seqform was changed
1251  * (interesting for ALTER SEQUENCE). Also set *owned_by to any OWNED BY
1252  * option, or to NIL if there is none.
1253  *
1254  * If isInit is true, fill any unspecified options with default values;
1255  * otherwise, do not change existing options that aren't explicitly overridden.
1256  */
1257 static void
1258 init_params(ParseState *pstate, List *options, bool for_identity,
1259  bool isInit,
1260  Form_pg_sequence seqform,
1261  bool *changed_seqform,
1262  Form_pg_sequence_data seqdataform,
1263  List **owned_by)
1264 {
1265  DefElem *as_type = NULL;
1266  DefElem *start_value = NULL;
1267  DefElem *restart_value = NULL;
1268  DefElem *increment_by = NULL;
1269  DefElem *max_value = NULL;
1270  DefElem *min_value = NULL;
1271  DefElem *cache_value = NULL;
1272  DefElem *is_cycled = NULL;
1273  ListCell *option;
1274  bool reset_max_value = false;
1275  bool reset_min_value = false;
1276 
1277  *owned_by = NIL;
1278 
1279  foreach(option, options)
1280  {
1281  DefElem *defel = (DefElem *) lfirst(option);
1282 
1283  if (strcmp(defel->defname, "as") == 0)
1284  {
1285  if (as_type)
1286  ereport(ERROR,
1287  (errcode(ERRCODE_SYNTAX_ERROR),
1288  errmsg("conflicting or redundant options"),
1289  parser_errposition(pstate, defel->location)));
1290  as_type = defel;
1291  }
1292  else if (strcmp(defel->defname, "increment") == 0)
1293  {
1294  if (increment_by)
1295  ereport(ERROR,
1296  (errcode(ERRCODE_SYNTAX_ERROR),
1297  errmsg("conflicting or redundant options"),
1298  parser_errposition(pstate, defel->location)));
1299  increment_by = defel;
1300  }
1301  else if (strcmp(defel->defname, "start") == 0)
1302  {
1303  if (start_value)
1304  ereport(ERROR,
1305  (errcode(ERRCODE_SYNTAX_ERROR),
1306  errmsg("conflicting or redundant options"),
1307  parser_errposition(pstate, defel->location)));
1308  start_value = defel;
1309  }
1310  else if (strcmp(defel->defname, "restart") == 0)
1311  {
1312  if (restart_value)
1313  ereport(ERROR,
1314  (errcode(ERRCODE_SYNTAX_ERROR),
1315  errmsg("conflicting or redundant options"),
1316  parser_errposition(pstate, defel->location)));
1317  restart_value = defel;
1318  }
1319  else if (strcmp(defel->defname, "maxvalue") == 0)
1320  {
1321  if (max_value)
1322  ereport(ERROR,
1323  (errcode(ERRCODE_SYNTAX_ERROR),
1324  errmsg("conflicting or redundant options"),
1325  parser_errposition(pstate, defel->location)));
1326  max_value = defel;
1327  }
1328  else if (strcmp(defel->defname, "minvalue") == 0)
1329  {
1330  if (min_value)
1331  ereport(ERROR,
1332  (errcode(ERRCODE_SYNTAX_ERROR),
1333  errmsg("conflicting or redundant options"),
1334  parser_errposition(pstate, defel->location)));
1335  min_value = defel;
1336  }
1337  else if (strcmp(defel->defname, "cache") == 0)
1338  {
1339  if (cache_value)
1340  ereport(ERROR,
1341  (errcode(ERRCODE_SYNTAX_ERROR),
1342  errmsg("conflicting or redundant options"),
1343  parser_errposition(pstate, defel->location)));
1344  cache_value = defel;
1345  }
1346  else if (strcmp(defel->defname, "cycle") == 0)
1347  {
1348  if (is_cycled)
1349  ereport(ERROR,
1350  (errcode(ERRCODE_SYNTAX_ERROR),
1351  errmsg("conflicting or redundant options"),
1352  parser_errposition(pstate, defel->location)));
1353  is_cycled = defel;
1354  }
1355  else if (strcmp(defel->defname, "owned_by") == 0)
1356  {
1357  if (*owned_by)
1358  ereport(ERROR,
1359  (errcode(ERRCODE_SYNTAX_ERROR),
1360  errmsg("conflicting or redundant options"),
1361  parser_errposition(pstate, defel->location)));
1362  *owned_by = defGetQualifiedName(defel);
1363  }
1364  else if (strcmp(defel->defname, "sequence_name") == 0)
1365  {
1366  /*
1367  * The parser allows this, but it is only for identity columns, in
1368  * which case it is filtered out in parse_utilcmd.c. We only get
1369  * here if someone puts it into a CREATE SEQUENCE.
1370  */
1371  ereport(ERROR,
1372  (errcode(ERRCODE_SYNTAX_ERROR),
1373  errmsg("invalid sequence option SEQUENCE NAME"),
1374  parser_errposition(pstate, defel->location)));
1375  }
1376  else
1377  elog(ERROR, "option \"%s\" not recognized",
1378  defel->defname);
1379  }
1380 
1381  *changed_seqform = false;
1382 
1383  /*
1384  * We must reset log_cnt when isInit or when changing any parameters that
1385  * would affect future nextval allocations.
1386  */
1387  if (isInit)
1388  seqdataform->log_cnt = 0;
1389 
1390  /* AS type */
1391  if (as_type != NULL)
1392  {
1393  Oid newtypid = typenameTypeId(pstate, defGetTypeName(as_type));
1394 
1395  if (newtypid != INT2OID &&
1396  newtypid != INT4OID &&
1397  newtypid != INT8OID)
1398  ereport(ERROR,
1399  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1400  for_identity
1401  ? errmsg("identity column type must be smallint, integer, or bigint")
1402  : errmsg("sequence type must be smallint, integer, or bigint")));
1403 
1404  if (!isInit)
1405  {
1406  /*
1407  * When changing type and the old sequence min/max values were the
1408  * min/max of the old type, adjust sequence min/max values to
1409  * min/max of new type. (Otherwise, the user chose explicit
1410  * min/max values, which we'll leave alone.)
1411  */
1412  if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX) ||
1413  (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX) ||
1414  (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX))
1415  reset_max_value = true;
1416  if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN) ||
1417  (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN) ||
1418  (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN))
1419  reset_min_value = true;
1420  }
1421 
1422  seqform->seqtypid = newtypid;
1423  *changed_seqform = true;
1424  }
1425  else if (isInit)
1426  {
1427  seqform->seqtypid = INT8OID;
1428  *changed_seqform = true;
1429  }
1430 
1431  /* INCREMENT BY */
1432  if (increment_by != NULL)
1433  {
1434  seqform->seqincrement = defGetInt64(increment_by);
1435  *changed_seqform = true;
1436  if (seqform->seqincrement == 0)
1437  ereport(ERROR,
1438  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1439  errmsg("INCREMENT must not be zero")));
1440  seqdataform->log_cnt = 0;
1441  }
1442  else if (isInit)
1443  {
1444  seqform->seqincrement = 1;
1445  *changed_seqform = true;
1446  }
1447 
1448  /* CYCLE */
1449  if (is_cycled != NULL)
1450  {
1451  seqform->seqcycle = intVal(is_cycled->arg);
1452  *changed_seqform = true;
1453  Assert(BoolIsValid(seqform->seqcycle));
1454  seqdataform->log_cnt = 0;
1455  }
1456  else if (isInit)
1457  {
1458  seqform->seqcycle = false;
1459  *changed_seqform = true;
1460  }
1461 
1462  /* MAXVALUE (null arg means NO MAXVALUE) */
1463  if (max_value != NULL && max_value->arg)
1464  {
1465  seqform->seqmax = defGetInt64(max_value);
1466  *changed_seqform = true;
1467  seqdataform->log_cnt = 0;
1468  }
1469  else if (isInit || max_value != NULL || reset_max_value)
1470  {
1471  if (seqform->seqincrement > 0 || reset_max_value)
1472  {
1473  /* ascending seq */
1474  if (seqform->seqtypid == INT2OID)
1475  seqform->seqmax = PG_INT16_MAX;
1476  else if (seqform->seqtypid == INT4OID)
1477  seqform->seqmax = PG_INT32_MAX;
1478  else
1479  seqform->seqmax = PG_INT64_MAX;
1480  }
1481  else
1482  seqform->seqmax = -1; /* descending seq */
1483  *changed_seqform = true;
1484  seqdataform->log_cnt = 0;
1485  }
1486 
1487  if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
1488  || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX))
1489  || (seqform->seqtypid == INT8OID && (seqform->seqmax < PG_INT64_MIN || seqform->seqmax > PG_INT64_MAX)))
1490  {
1491  char bufx[100];
1492 
1493  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1494 
1495  ereport(ERROR,
1496  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1497  errmsg("MAXVALUE (%s) is out of range for sequence data type %s",
1498  bufx, format_type_be(seqform->seqtypid))));
1499  }
1500 
1501  /* MINVALUE (null arg means NO MINVALUE) */
1502  if (min_value != NULL && min_value->arg)
1503  {
1504  seqform->seqmin = defGetInt64(min_value);
1505  *changed_seqform = true;
1506  seqdataform->log_cnt = 0;
1507  }
1508  else if (isInit || min_value != NULL || reset_min_value)
1509  {
1510  if (seqform->seqincrement < 0 || reset_min_value)
1511  {
1512  /* descending seq */
1513  if (seqform->seqtypid == INT2OID)
1514  seqform->seqmin = PG_INT16_MIN;
1515  else if (seqform->seqtypid == INT4OID)
1516  seqform->seqmin = PG_INT32_MIN;
1517  else
1518  seqform->seqmin = PG_INT64_MIN;
1519  }
1520  else
1521  seqform->seqmin = 1; /* ascending seq */
1522  *changed_seqform = true;
1523  seqdataform->log_cnt = 0;
1524  }
1525 
1526  if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
1527  || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX))
1528  || (seqform->seqtypid == INT8OID && (seqform->seqmin < PG_INT64_MIN || seqform->seqmin > PG_INT64_MAX)))
1529  {
1530  char bufm[100];
1531 
1532  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1533 
1534  ereport(ERROR,
1535  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1536  errmsg("MINVALUE (%s) is out of range for sequence data type %s",
1537  bufm, format_type_be(seqform->seqtypid))));
1538  }
1539 
1540  /* crosscheck min/max */
1541  if (seqform->seqmin >= seqform->seqmax)
1542  {
1543  char bufm[100],
1544  bufx[100];
1545 
1546  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1547  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1548  ereport(ERROR,
1549  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1550  errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
1551  bufm, bufx)));
1552  }
1553 
1554  /* START WITH */
1555  if (start_value != NULL)
1556  {
1557  seqform->seqstart = defGetInt64(start_value);
1558  *changed_seqform = true;
1559  }
1560  else if (isInit)
1561  {
1562  if (seqform->seqincrement > 0)
1563  seqform->seqstart = seqform->seqmin; /* ascending seq */
1564  else
1565  seqform->seqstart = seqform->seqmax; /* descending seq */
1566  *changed_seqform = true;
1567  }
1568 
1569  /* crosscheck START */
1570  if (seqform->seqstart < seqform->seqmin)
1571  {
1572  char bufs[100],
1573  bufm[100];
1574 
1575  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1576  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1577  ereport(ERROR,
1578  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1579  errmsg("START value (%s) cannot be less than MINVALUE (%s)",
1580  bufs, bufm)));
1581  }
1582  if (seqform->seqstart > seqform->seqmax)
1583  {
1584  char bufs[100],
1585  bufm[100];
1586 
1587  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1588  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1589  ereport(ERROR,
1590  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1591  errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
1592  bufs, bufm)));
1593  }
1594 
1595  /* RESTART [WITH] */
1596  if (restart_value != NULL)
1597  {
1598  if (restart_value->arg != NULL)
1599  seqdataform->last_value = defGetInt64(restart_value);
1600  else
1601  seqdataform->last_value = seqform->seqstart;
1602  seqdataform->is_called = false;
1603  seqdataform->log_cnt = 0;
1604  }
1605  else if (isInit)
1606  {
1607  seqdataform->last_value = seqform->seqstart;
1608  seqdataform->is_called = false;
1609  }
1610 
1611  /* crosscheck RESTART (or current value, if changing MIN/MAX) */
1612  if (seqdataform->last_value < seqform->seqmin)
1613  {
1614  char bufs[100],
1615  bufm[100];
1616 
1617  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1618  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1619  ereport(ERROR,
1620  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1621  errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
1622  bufs, bufm)));
1623  }
1624  if (seqdataform->last_value > seqform->seqmax)
1625  {
1626  char bufs[100],
1627  bufm[100];
1628 
1629  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1630  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1631  ereport(ERROR,
1632  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1633  errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
1634  bufs, bufm)));
1635  }
1636 
1637  /* CACHE */
1638  if (cache_value != NULL)
1639  {
1640  seqform->seqcache = defGetInt64(cache_value);
1641  *changed_seqform = true;
1642  if (seqform->seqcache <= 0)
1643  {
1644  char buf[100];
1645 
1646  snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
1647  ereport(ERROR,
1648  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1649  errmsg("CACHE (%s) must be greater than zero",
1650  buf)));
1651  }
1652  seqdataform->log_cnt = 0;
1653  }
1654  else if (isInit)
1655  {
1656  seqform->seqcache = 1;
1657  *changed_seqform = true;
1658  }
1659 }
1660 
1661 /*
1662  * Process an OWNED BY option for CREATE/ALTER SEQUENCE
1663  *
1664  * Ownership permissions on the sequence are already checked,
1665  * but if we are establishing a new owned-by dependency, we must
1666  * enforce that the referenced table has the same owner and namespace
1667  * as the sequence.
1668  */
1669 static void
1670 process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
1671 {
1672  DependencyType deptype;
1673  int nnames;
1674  Relation tablerel;
1675  AttrNumber attnum;
1676 
1677  deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO;
1678 
1679  nnames = list_length(owned_by);
1680  Assert(nnames > 0);
1681  if (nnames == 1)
1682  {
1683  /* Must be OWNED BY NONE */
1684  if (strcmp(strVal(linitial(owned_by)), "none") != 0)
1685  ereport(ERROR,
1686  (errcode(ERRCODE_SYNTAX_ERROR),
1687  errmsg("invalid OWNED BY option"),
1688  errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
1689  tablerel = NULL;
1690  attnum = 0;
1691  }
1692  else
1693  {
1694  List *relname;
1695  char *attrname;
1696  RangeVar *rel;
1697 
1698  /* Separate relname and attr name */
1699  relname = list_truncate(list_copy(owned_by), nnames - 1);
1700  attrname = strVal(lfirst(list_tail(owned_by)));
1701 
1702  /* Open and lock rel to ensure it won't go away meanwhile */
1703  rel = makeRangeVarFromNameList(relname);
1704  tablerel = relation_openrv(rel, AccessShareLock);
1705 
1706  /* Must be a regular or foreign table */
1707  if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
1708  tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1709  tablerel->rd_rel->relkind == RELKIND_VIEW ||
1710  tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1711  ereport(ERROR,
1712  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1713  errmsg("referenced relation \"%s\" is not a table or foreign table",
1714  RelationGetRelationName(tablerel))));
1715 
1716  /* We insist on same owner and schema */
1717  if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
1718  ereport(ERROR,
1719  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1720  errmsg("sequence must have same owner as table it is linked to")));
1721  if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
1722  ereport(ERROR,
1723  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1724  errmsg("sequence must be in same schema as table it is linked to")));
1725 
1726  /* Now, fetch the attribute number from the system cache */
1727  attnum = get_attnum(RelationGetRelid(tablerel), attrname);
1728  if (attnum == InvalidAttrNumber)
1729  ereport(ERROR,
1730  (errcode(ERRCODE_UNDEFINED_COLUMN),
1731  errmsg("column \"%s\" of relation \"%s\" does not exist",
1732  attrname, RelationGetRelationName(tablerel))));
1733  }
1734 
1735  /*
1736  * Catch user explicitly running OWNED BY on identity sequence.
1737  */
1738  if (deptype == DEPENDENCY_AUTO)
1739  {
1740  Oid tableId;
1741  int32 colId;
1742 
1743  if (sequenceIsOwned(RelationGetRelid(seqrel), DEPENDENCY_INTERNAL, &tableId, &colId))
1744  ereport(ERROR,
1745  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1746  errmsg("cannot change ownership of identity sequence"),
1747  errdetail("Sequence \"%s\" is linked to table \"%s\".",
1748  RelationGetRelationName(seqrel),
1749  get_rel_name(tableId))));
1750  }
1751 
1752  /*
1753  * OK, we are ready to update pg_depend. First remove any existing
1754  * dependencies for the sequence, then optionally add a new one.
1755  */
1757  RelationRelationId, deptype);
1758 
1759  if (tablerel)
1760  {
1761  ObjectAddress refobject,
1762  depobject;
1763 
1764  refobject.classId = RelationRelationId;
1765  refobject.objectId = RelationGetRelid(tablerel);
1766  refobject.objectSubId = attnum;
1767  depobject.classId = RelationRelationId;
1768  depobject.objectId = RelationGetRelid(seqrel);
1769  depobject.objectSubId = 0;
1770  recordDependencyOn(&depobject, &refobject, deptype);
1771  }
1772 
1773  /* Done, but hold lock until commit */
1774  if (tablerel)
1775  relation_close(tablerel, NoLock);
1776 }
1777 
1778 
1779 /*
1780  * Return sequence parameters in a list of the form created by the parser.
1781  */
1782 List *
1784 {
1785  HeapTuple pgstuple;
1786  Form_pg_sequence pgsform;
1787  List *options = NIL;
1788 
1789  pgstuple = SearchSysCache1(SEQRELID, relid);
1790  if (!HeapTupleIsValid(pgstuple))
1791  elog(ERROR, "cache lookup failed for sequence %u", relid);
1792  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1793 
1794  options = lappend(options, makeDefElem("cache", (Node *) makeInteger(pgsform->seqcache), -1));
1795  options = lappend(options, makeDefElem("cycle", (Node *) makeInteger(pgsform->seqcycle), -1));
1796  options = lappend(options, makeDefElem("increment", (Node *) makeInteger(pgsform->seqincrement), -1));
1797  options = lappend(options, makeDefElem("maxvalue", (Node *) makeInteger(pgsform->seqmax), -1));
1798  options = lappend(options, makeDefElem("minvalue", (Node *) makeInteger(pgsform->seqmin), -1));
1799  options = lappend(options, makeDefElem("start", (Node *) makeInteger(pgsform->seqstart), -1));
1800 
1801  ReleaseSysCache(pgstuple);
1802 
1803  return options;
1804 }
1805 
1806 /*
1807  * Return sequence parameters (formerly for use by information schema)
1808  */
1809 Datum
1811 {
1812  Oid relid = PG_GETARG_OID(0);
1813  TupleDesc tupdesc;
1814  Datum values[7];
1815  bool isnull[7];
1816  HeapTuple pgstuple;
1817  Form_pg_sequence pgsform;
1818 
1820  ereport(ERROR,
1821  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1822  errmsg("permission denied for sequence %s",
1823  get_rel_name(relid))));
1824 
1825  tupdesc = CreateTemplateTupleDesc(7, false);
1826  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
1827  INT8OID, -1, 0);
1828  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
1829  INT8OID, -1, 0);
1830  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
1831  INT8OID, -1, 0);
1832  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
1833  INT8OID, -1, 0);
1834  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
1835  BOOLOID, -1, 0);
1836  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size",
1837  INT8OID, -1, 0);
1838  TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type",
1839  OIDOID, -1, 0);
1840 
1841  BlessTupleDesc(tupdesc);
1842 
1843  memset(isnull, 0, sizeof(isnull));
1844 
1845  pgstuple = SearchSysCache1(SEQRELID, relid);
1846  if (!HeapTupleIsValid(pgstuple))
1847  elog(ERROR, "cache lookup failed for sequence %u", relid);
1848  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1849 
1850  values[0] = Int64GetDatum(pgsform->seqstart);
1851  values[1] = Int64GetDatum(pgsform->seqmin);
1852  values[2] = Int64GetDatum(pgsform->seqmax);
1853  values[3] = Int64GetDatum(pgsform->seqincrement);
1854  values[4] = BoolGetDatum(pgsform->seqcycle);
1855  values[5] = Int64GetDatum(pgsform->seqcache);
1856  values[6] = ObjectIdGetDatum(pgsform->seqtypid);
1857 
1858  ReleaseSysCache(pgstuple);
1859 
1860  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
1861 }
1862 
1863 /*
1864  * Return the last value from the sequence
1865  *
1866  * Note: This has a completely different meaning than lastval().
1867  */
1868 Datum
1870 {
1871  Oid relid = PG_GETARG_OID(0);
1872  SeqTable elm;
1873  Relation seqrel;
1874  Buffer buf;
1875  HeapTupleData seqtuple;
1877  bool is_called;
1878  int64 result;
1879 
1880  /* open and lock sequence */
1881  init_sequence(relid, &elm, &seqrel);
1882 
1884  ereport(ERROR,
1885  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1886  errmsg("permission denied for sequence %s",
1887  RelationGetRelationName(seqrel))));
1888 
1889  seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1890 
1891  is_called = seq->is_called;
1892  result = seq->last_value;
1893 
1894  UnlockReleaseBuffer(buf);
1895  relation_close(seqrel, NoLock);
1896 
1897  if (is_called)
1898  PG_RETURN_INT64(result);
1899  else
1900  PG_RETURN_NULL();
1901 }
1902 
1903 
1904 void
1906 {
1907  XLogRecPtr lsn = record->EndRecPtr;
1908  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1909  Buffer buffer;
1910  Page page;
1911  Page localpage;
1912  char *item;
1913  Size itemsz;
1914  xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1915  sequence_magic *sm;
1916 
1917  if (info != XLOG_SEQ_LOG)
1918  elog(PANIC, "seq_redo: unknown op code %u", info);
1919 
1920  buffer = XLogInitBufferForRedo(record, 0);
1921  page = (Page) BufferGetPage(buffer);
1922 
1923  /*
1924  * We always reinit the page. However, since this WAL record type is also
1925  * used for updating sequences, it's possible that a hot-standby backend
1926  * is examining the page concurrently; so we mustn't transiently trash the
1927  * buffer. The solution is to build the correct new page contents in
1928  * local workspace and then memcpy into the buffer. Then only bytes that
1929  * are supposed to change will change, even transiently. We must palloc
1930  * the local page for alignment reasons.
1931  */
1932  localpage = (Page) palloc(BufferGetPageSize(buffer));
1933 
1934  PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1935  sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1936  sm->magic = SEQ_MAGIC;
1937 
1938  item = (char *) xlrec + sizeof(xl_seq_rec);
1939  itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1940 
1941  if (PageAddItem(localpage, (Item) item, itemsz,
1942  FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1943  elog(PANIC, "seq_redo: failed to add item to page");
1944 
1945  PageSetLSN(localpage, lsn);
1946 
1947  memcpy(page, localpage, BufferGetPageSize(buffer));
1948  MarkBufferDirty(buffer);
1949  UnlockReleaseBuffer(buffer);
1950 
1951  pfree(localpage);
1952 }
1953 
1954 /*
1955  * Flush cached sequence information.
1956  */
1957 void
1959 {
1960  if (seqhashtab)
1961  {
1962  hash_destroy(seqhashtab);
1963  seqhashtab = NULL;
1964  }
1965 
1966  last_used_seq = NULL;
1967 }
1968 
1969 /*
1970  * Mask a Sequence page before performing consistency checks on it.
1971  */
1972 void
1973 seq_mask(char *page, BlockNumber blkno)
1974 {
1975  mask_page_lsn(page);
1976 
1977  mask_unused_space(page);
1978 }
RangeVar * relation
Definition: parsenodes.h:1968
ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
Definition: sequence.c:414
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define NIL
Definition: pg_list.h:69
DependencyType
Definition: dependency.h:73
OnCommitAction oncommit
Definition: parsenodes.h:1977
int64 cached
Definition: sequence.c:79
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1192
List * inhRelations
Definition: parsenodes.h:1970
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3416
Datum currval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:828
int errhint(const char *fmt,...)
Definition: elog.c:987
#define PG_INT64_MAX
Definition: c.h:343
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static int32 next
Definition: blutils.c:210
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:254
char storage
Definition: parsenodes.h:647
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
#define HASH_ELEM
Definition: hsearch.h:87
#define SEQ_MAGIC
Definition: sequence.c:59
bool is_local
Definition: parsenodes.h:643
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
#define RelationGetDescr(relation)
Definition: rel.h:429
int LOCKMODE
Definition: lockdefs.h:26
Oid GetUserId(void)
Definition: miscinit.c:283
struct xl_seq_rec xl_seq_rec
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
#define OIDOID
Definition: pg_type.h:328
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
PGPROC * MyProc
Definition: proc.c:67
bool last_valid
Definition: sequence.c:77
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
List * constraints
Definition: parsenodes.h:653
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static void check_permissions(void)
Definition: logicalfuncs.c:109
#define RelationRelationId
Definition: pg_class.h:29
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:577
bool if_not_exists
Definition: parsenodes.h:2438
bool is_from_parent
Definition: parsenodes.h:646
bool rd_islocaltemp
Definition: rel.h:90
Datum nextval(PG_FUNCTION_ARGS)
Definition: sequence.c:547
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
unsigned char uint8
Definition: c.h:266
List * list_truncate(List *list, int new_size)
Definition: list.c:350
Pointer Item
Definition: item.h:17
#define AccessShareLock
Definition: lockdefs.h:36
#define INT4OID
Definition: pg_type.h:316
Size entrysize
Definition: hsearch.h:73
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
Definition: nodes.h:509
#define strVal(v)
Definition: value.h:54
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
#define Anum_pg_sequence_seqcache
Definition: pg_sequence.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
void seq_redo(XLogReaderState *record)
Definition: sequence.c:1905
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:413
#define SequenceRelationId
Definition: pg_sequence.h:6
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define SEQ_COL_FIRSTCOL
Definition: sequence.h:42
return result
Definition: formatting.c:1632
int64 defGetInt64(DefElem *def)
Definition: define.c:190
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
uint32 BlockNumber
Definition: block.h:31
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
struct SeqTableData SeqTableData
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2980
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, bool *changed_seqform, Form_pg_sequence_data seqdataform, List **owned_by)
Definition: sequence.c:1258
#define P_NEW
Definition: bufmgr.h:82
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
bool is_not_null
Definition: parsenodes.h:644
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
RelFileNode node
Definition: sequence.h:50
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define PANIC
Definition: elog.h:53
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:544
#define Anum_pg_sequence_seqtypid
Definition: pg_sequence.h:24
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
List * options
Definition: parsenodes.h:2445
void mask_unused_space(Page page)
Definition: bufmask.c:69
signed int int32
Definition: c.h:256
#define FirstCommandId
Definition: c.h:413
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
List * constraints
Definition: parsenodes.h:1975
bool if_not_exists
Definition: parsenodes.h:1979
Node * cooked_default
Definition: parsenodes.h:649
char * relname
Definition: primnodes.h:68
Value * makeInteger(long i)
Definition: value.c:23
Definition: dynahash.c:193
static ListCell * list_tail(List *l)
Definition: pg_list.h:83
static HTAB * seqhashtab
Definition: sequence.c:87
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:174
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
void pfree(void *pointer)
Definition: mcxt.c:950
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
Datum nextval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:569
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
#define linitial(l)
Definition: pg_list.h:111
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define SEQ_COL_LASTVAL
Definition: sequence.h:38
FormData_pg_sequence
Definition: pg_sequence.h:18
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static void create_seq_hashtable(void)
Definition: sequence.c:1092
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:221
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
void mask_page_lsn(Page page)
Definition: bufmask.c:30
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
Datum pg_sequence_parameters(PG_FUNCTION_ARGS)
Definition: sequence.c:1810
ItemPointerData t_ctid
Definition: htup_details.h:150
#define Natts_pg_sequence
Definition: pg_sequence.h:22
ItemPointerData t_self
Definition: htup.h:65
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define INT2OID
Definition: pg_type.h:308
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define PG_INT64_MIN
Definition: c.h:342
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
Oid collOid
Definition: parsenodes.h:652
int location
Definition: parsenodes.h:723
#define FirstOffsetNumber
Definition: off.h:27
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:907
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:437
List * options
Definition: parsenodes.h:1976
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1670
unsigned int uint32
Definition: c.h:268
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:80
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
int location
Definition: parsenodes.h:655
uint32 LocalTransactionId
Definition: c.h:399
void DeleteSequenceTuple(Oid relid)
Definition: sequence.c:524
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:497
#define PG_INT16_MIN
Definition: c.h:336
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PG_INT32_MIN
Definition: c.h:339
ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
Definition: sequence.c:116
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:489
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:216
#define SEQ_COL_LOG
Definition: sequence.h:39
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1176
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3189
Node * arg
Definition: parsenodes.h:721
Node * raw_default
Definition: parsenodes.h:648
List * lappend(List *list, void *datum)
Definition: list.c:128
char * tablespacename
Definition: parsenodes.h:1978
static char ** options
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
#define HASH_BLOBS
Definition: hsearch.h:88
#define ACL_UPDATE
Definition: parsenodes.h:74
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
SeqTableData * SeqTable
Definition: sequence.c:85
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
uintptr_t Datum
Definition: postgres.h:372
#define Anum_pg_sequence_seqmin
Definition: pg_sequence.h:28
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define ACL_SELECT
Definition: parsenodes.h:73
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define Anum_pg_sequence_seqcycle
Definition: pg_sequence.h:30
Oid filenode
Definition: sequence.c:75
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define Int64GetDatumFast(X)
Definition: postgres.h:781
Size keysize
Definition: hsearch.h:72
#define InvalidMultiXactId
Definition: multixact.h:23
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
void seq_mask(char *page, BlockNumber blkno)
Definition: sequence.c:1973
#define BoolGetDatum(X)
Definition: postgres.h:408
#define InvalidOffsetNumber
Definition: off.h:26
TypeName * makeTypeNameFromOid(Oid typeOid, int32 typmod)
Definition: makefuncs.c:469
#define InvalidOid
Definition: postgres_ext.h:36
RangeVar * sequence
Definition: parsenodes.h:2444
void ResetSequenceCaches(void)
Definition: sequence.c:1958
RangeVar * sequence
Definition: parsenodes.h:2434
bool is_from_type
Definition: parsenodes.h:645
#define NOTICE
Definition: elog.h:37
#define INT8OID
Definition: pg_type.h:304
List * tableElts
Definition: parsenodes.h:1969
struct sequence_magic sequence_magic
RelFileNode rd_node
Definition: rel.h:85
#define PG_CATCH()
Definition: elog.h:293
#define makeNode(_type_)
Definition: nodes.h:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define SEQ_LOG_VALS
Definition: sequence.c:54
#define lfirst(lc)
Definition: pg_list.h:106
int64 increment
Definition: sequence.c:81
#define ShareRowExclusiveLock
Definition: lockdefs.h:42
#define FrozenTransactionId
Definition: transam.h:33
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:211
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint32 magic
Definition: sequence.c:63
size_t Size
Definition: c.h:356
#define PageGetSpecialPointer(page)
Definition: bufpage.h:323
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Datum lastval(PG_FUNCTION_ARGS)
Definition: sequence.c:859
TypeName * typeName
Definition: parsenodes.h:641
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8163
CollateClause * collClause
Definition: parsenodes.h:651
#define PG_INT16_MAX
Definition: c.h:337
#define Anum_pg_sequence_seqstart
Definition: pg_sequence.h:25
#define PG_RE_THROW()
Definition: elog.h:314
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define BOOLOID
Definition: pg_type.h:288
#define RelationNeedsWAL(relation)
Definition: rel.h:506
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
LocalTransactionId lxid
Definition: sequence.c:76
#define INT64_FORMAT
Definition: c.h:315
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:236
#define InvalidAttrNumber
Definition: attnum.h:23
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static SeqTableData * last_used_seq
Definition: sequence.c:93
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
char relpersistence
Definition: primnodes.h:71
#define PageGetLSN(page)
Definition: bufpage.h:363
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define SEQ_COL_LASTCOL
Definition: sequence.h:43
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
#define AccessExclusiveLock
Definition: lockdefs.h:46
Datum setval3_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:1035
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1109
#define intVal(v)
Definition: value.h:52
const ObjectAddress InvalidObjectAddress
void * palloc(Size size)
Definition: mcxt.c:849
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
Datum setval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:1020
#define PG_INT32_MAX
Definition: c.h:340
#define RELKIND_VIEW
Definition: pg_class.h:164
#define InvalidLocalTransactionId
Definition: lock.h:70
int i
int inhcount
Definition: parsenodes.h:642
#define HeapTupleHeaderSetXminFrozen(tup)
Definition: htup_details.h:346
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
static LOCKMODE alter_sequence_get_lock_level(List *options)
Definition: sequence.c:1231
bool for_identity
Definition: parsenodes.h:2446
Definition: c.h:439
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
char * defname
Definition: parsenodes.h:720
char * colname
Definition: parsenodes.h:640
#define Anum_pg_sequence_seqincrement
Definition: pg_sequence.h:26
#define elog
Definition: elog.h:219
#define Anum_pg_sequence_seqmax
Definition: pg_sequence.h:27
static struct @121 value
static Relation lock_and_open_sequence(SeqTable seq)
Definition: sequence.c:1056
void ResetSequence(Oid seq_relid)
Definition: sequence.c:267
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define XLOG_SEQ_LOG
Definition: sequence.h:46
#define PG_TRY()
Definition: elog.h:284
#define RELKIND_RELATION
Definition: pg_class.h:160
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
List * sequence_options(Oid relid)
Definition: sequence.c:1783
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
int Buffer
Definition: buf.h:23
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:335
int16 AttrNumber
Definition: attnum.h:21
Datum pg_sequence_last_value(PG_FUNCTION_ARGS)
Definition: sequence.c:1869
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_END_TRY()
Definition: elog.h:300
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:391
#define BoolIsValid(boolean)
Definition: c.h:520
#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
List * options
Definition: parsenodes.h:2435
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:104
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
LocalTransactionId lxid
Definition: proc.h:105
#define RelationGetNamespace(relation)
Definition: rel.h:444
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:313