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