LCOV - code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 666 698 95.4 %
Date: 2024-11-21 09:14:53 Functions: 28 28 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14