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