LCOV - code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 673 705 95.5 %
Date: 2025-08-20 15:17:26 Functions: 28 28 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.16