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