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