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

Generated by: LCOV version 2.0-1