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