LCOV - code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 640 676 94.7 %
Date: 2024-07-27 00:11:07 Functions: 26 27 96.3 %
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        1746 : 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        1746 :     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        1746 :     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        1736 :     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        1664 :     stmt->tableElts = NIL;
     174        6656 :     for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
     175             :     {
     176        4992 :         ColumnDef  *coldef = NULL;
     177             : 
     178        4992 :         switch (i)
     179             :         {
     180        1664 :             case SEQ_COL_LASTVAL:
     181        1664 :                 coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
     182        1664 :                 value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
     183        1664 :                 break;
     184        1664 :             case SEQ_COL_LOG:
     185        1664 :                 coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid);
     186        1664 :                 value[i - 1] = Int64GetDatum((int64) 0);
     187        1664 :                 break;
     188        1664 :             case SEQ_COL_CALLED:
     189        1664 :                 coldef = makeColumnDef("is_called", BOOLOID, -1, InvalidOid);
     190        1664 :                 value[i - 1] = BoolGetDatum(false);
     191        1664 :                 break;
     192             :         }
     193             : 
     194        4992 :         coldef->is_not_null = true;
     195        4992 :         null[i - 1] = false;
     196             : 
     197        4992 :         stmt->tableElts = lappend(stmt->tableElts, coldef);
     198             :     }
     199             : 
     200        1664 :     stmt->relation = seq->sequence;
     201        1664 :     stmt->inhRelations = NIL;
     202        1664 :     stmt->constraints = NIL;
     203        1664 :     stmt->options = NIL;
     204        1664 :     stmt->oncommit = ONCOMMIT_NOOP;
     205        1664 :     stmt->tablespacename = NULL;
     206        1664 :     stmt->if_not_exists = seq->if_not_exists;
     207             : 
     208        1664 :     address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
     209        1664 :     seqoid = address.objectId;
     210             :     Assert(seqoid != InvalidOid);
     211             : 
     212        1664 :     rel = sequence_open(seqoid, AccessExclusiveLock);
     213        1664 :     tupDesc = RelationGetDescr(rel);
     214             : 
     215             :     /* now initialize the sequence's data */
     216        1664 :     tuple = heap_form_tuple(tupDesc, value, null);
     217        1664 :     fill_seq_with_data(rel, tuple);
     218             : 
     219             :     /* process OWNED BY if given */
     220        1664 :     if (owned_by)
     221          26 :         process_owned_by(rel, owned_by, seq->for_identity);
     222             : 
     223        1640 :     sequence_close(rel, NoLock);
     224             : 
     225             :     /* fill in pg_sequence */
     226        1640 :     rel = table_open(SequenceRelationId, RowExclusiveLock);
     227        1640 :     tupDesc = RelationGetDescr(rel);
     228             : 
     229        1640 :     memset(pgs_nulls, 0, sizeof(pgs_nulls));
     230             : 
     231        1640 :     pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
     232        1640 :     pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
     233        1640 :     pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
     234        1640 :     pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
     235        1640 :     pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
     236        1640 :     pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
     237        1640 :     pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
     238        1640 :     pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
     239             : 
     240        1640 :     tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
     241        1640 :     CatalogTupleInsert(rel, tuple);
     242             : 
     243        1640 :     heap_freetuple(tuple);
     244        1640 :     table_close(rel, RowExclusiveLock);
     245             : 
     246        1640 :     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        1934 : fill_seq_with_data(Relation rel, HeapTuple tuple)
     339             : {
     340        1934 :     fill_seq_fork_with_data(rel, tuple, MAIN_FORKNUM);
     341             : 
     342        1934 :     if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
     343             :     {
     344             :         SMgrRelation srel;
     345             : 
     346         102 :         srel = smgropen(rel->rd_locator, INVALID_PROC_NUMBER);
     347         102 :         smgrcreate(srel, INIT_FORKNUM, false);
     348         102 :         log_smgrcreate(&rel->rd_locator, INIT_FORKNUM);
     349         102 :         fill_seq_fork_with_data(rel, tuple, INIT_FORKNUM);
     350         102 :         FlushRelationBuffers(rel);
     351         102 :         smgrclose(srel);
     352             :     }
     353        1934 : }
     354             : 
     355             : /*
     356             :  * Initialize a sequence's relation fork with the specified tuple as content
     357             :  */
     358             : static void
     359        2036 : 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        2036 :     buf = ExtendBufferedRel(BMR_REL(rel), forkNum, NULL,
     369             :                             EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
     370             :     Assert(BufferGetBlockNumber(buf) == 0);
     371             : 
     372        2036 :     page = BufferGetPage(buf);
     373             : 
     374        2036 :     PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
     375        2036 :     sm = (sequence_magic *) PageGetSpecialPointer(page);
     376        2036 :     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        2036 :     HeapTupleHeaderSetXmin(tuple->t_data, FrozenTransactionId);
     388        2036 :     HeapTupleHeaderSetXminFrozen(tuple->t_data);
     389        2036 :     HeapTupleHeaderSetCmin(tuple->t_data, FirstCommandId);
     390        2036 :     HeapTupleHeaderSetXmax(tuple->t_data, InvalidTransactionId);
     391        2036 :     tuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
     392        2036 :     ItemPointerSet(&tuple->t_data->t_ctid, 0, FirstOffsetNumber);
     393             : 
     394             :     /* check the comment above nextval_internal()'s equivalent call. */
     395        2036 :     if (RelationNeedsWAL(rel))
     396        1106 :         GetTopTransactionId();
     397             : 
     398        2036 :     START_CRIT_SECTION();
     399             : 
     400        2036 :     MarkBufferDirty(buf);
     401             : 
     402        2036 :     offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
     403             :                          InvalidOffsetNumber, false, false);
     404        2036 :     if (offnum != FirstOffsetNumber)
     405           0 :         elog(ERROR, "failed to add sequence tuple to page");
     406             : 
     407             :     /* XLOG stuff */
     408        2036 :     if (RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM)
     409             :     {
     410             :         xl_seq_rec  xlrec;
     411             :         XLogRecPtr  recptr;
     412             : 
     413        1208 :         XLogBeginInsert();
     414        1208 :         XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
     415             : 
     416        1208 :         xlrec.locator = rel->rd_locator;
     417             : 
     418        1208 :         XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
     419        1208 :         XLogRegisterData((char *) tuple->t_data, tuple->t_len);
     420             : 
     421        1208 :         recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
     422             : 
     423        1208 :         PageSetLSN(page, recptr);
     424             :     }
     425             : 
     426        2036 :     END_CRIT_SECTION();
     427             : 
     428        2036 :     UnlockReleaseBuffer(buf);
     429        2036 : }
     430             : 
     431             : /*
     432             :  * AlterSequence
     433             :  *
     434             :  * Modify the definition of a sequence relation
     435             :  */
     436             : ObjectAddress
     437        1380 : 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        1380 :     relid = RangeVarGetRelidExtended(stmt->sequence,
     455             :                                      ShareRowExclusiveLock,
     456        1380 :                                      stmt->missing_ok ? RVR_MISSING_OK : 0,
     457             :                                      RangeVarCallbackOwnsRelation,
     458             :                                      NULL);
     459        1374 :     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        1368 :     init_sequence(relid, &elm, &seqrel);
     468             : 
     469        1362 :     rel = table_open(SequenceRelationId, RowExclusiveLock);
     470        1362 :     seqtuple = SearchSysCacheCopy1(SEQRELID,
     471             :                                    ObjectIdGetDatum(relid));
     472        1362 :     if (!HeapTupleIsValid(seqtuple))
     473           0 :         elog(ERROR, "cache lookup failed for sequence %u",
     474             :              relid);
     475             : 
     476        1362 :     seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
     477             : 
     478             :     /* lock page buffer and read tuple into new sequence structure */
     479        1362 :     (void) read_seq_tuple(seqrel, &buf, &datatuple);
     480             : 
     481             :     /* copy the existing sequence data tuple, so it can be modified locally */
     482        1362 :     newdatatuple = heap_copytuple(&datatuple);
     483        1362 :     newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
     484             : 
     485        1362 :     UnlockReleaseBuffer(buf);
     486             : 
     487             :     /* Check and set new values */
     488        1362 :     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        1332 :     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        1332 :     elm->cached = elm->last;
     522             : 
     523             :     /* process OWNED BY if given */
     524        1332 :     if (owned_by)
     525        1144 :         process_owned_by(seqrel, owned_by, stmt->for_identity);
     526             : 
     527             :     /* update the pg_sequence tuple (we could skip this in some cases...) */
     528        1326 :     CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple);
     529             : 
     530        1326 :     InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
     531             : 
     532        1326 :     ObjectAddressSet(address, RelationRelationId, relid);
     533             : 
     534        1326 :     table_close(rel, RowExclusiveLock);
     535        1326 :     sequence_close(seqrel, NoLock);
     536             : 
     537        1326 :     return address;
     538             : }
     539             : 
     540             : void
     541          60 : 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          60 :     LockRelationOid(relid, AccessExclusiveLock);
     555          60 :     init_sequence(relid, &elm, &seqrel);
     556             : 
     557             :     /* check the comment above nextval_internal()'s equivalent call. */
     558          60 :     if (RelationNeedsWAL(seqrel))
     559          34 :         GetTopTransactionId();
     560             : 
     561          60 :     (void) read_seq_tuple(seqrel, &buf, &seqdatatuple);
     562          60 :     RelationSetNewRelfilenumber(seqrel, newrelpersistence);
     563          60 :     fill_seq_with_data(seqrel, &seqdatatuple);
     564          60 :     UnlockReleaseBuffer(buf);
     565             : 
     566          60 :     sequence_close(seqrel, NoLock);
     567          60 : }
     568             : 
     569             : void
     570         930 : DeleteSequenceTuple(Oid relid)
     571             : {
     572             :     Relation    rel;
     573             :     HeapTuple   tuple;
     574             : 
     575         930 :     rel = table_open(SequenceRelationId, RowExclusiveLock);
     576             : 
     577         930 :     tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
     578         930 :     if (!HeapTupleIsValid(tuple))
     579           0 :         elog(ERROR, "cache lookup failed for sequence %u", relid);
     580             : 
     581         930 :     CatalogTupleDelete(rel, &tuple->t_self);
     582             : 
     583         930 :     ReleaseSysCache(tuple);
     584         930 :     table_close(rel, RowExclusiveLock);
     585         930 : }
     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      199918 : nextval_oid(PG_FUNCTION_ARGS)
     616             : {
     617      199918 :     Oid         relid = PG_GETARG_OID(0);
     618             : 
     619      199918 :     PG_RETURN_INT64(nextval_internal(relid, true));
     620             : }
     621             : 
     622             : int64
     623      200980 : 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      200980 :                 rescnt = 0;
     643             :     bool        cycle;
     644      200980 :     bool        logit = false;
     645             : 
     646             :     /* open and lock sequence */
     647      200980 :     init_sequence(relid, &elm, &seqrel);
     648             : 
     649      400940 :     if (check_permissions &&
     650      199960 :         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      200974 :     if (!seqrel->rd_islocaltemp)
     659       79238 :         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      200968 :     PreventCommandIfParallelMode("nextval()");
     667             : 
     668      200968 :     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      200956 :     pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
     679      200956 :     if (!HeapTupleIsValid(pgstuple))
     680           0 :         elog(ERROR, "cache lookup failed for sequence %u", relid);
     681      200956 :     pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
     682      200956 :     incby = pgsform->seqincrement;
     683      200956 :     maxv = pgsform->seqmax;
     684      200956 :     minv = pgsform->seqmin;
     685      200956 :     cache = pgsform->seqcache;
     686      200956 :     cycle = pgsform->seqcycle;
     687      200956 :     ReleaseSysCache(pgstuple);
     688             : 
     689             :     /* lock page buffer and read tuple */
     690      200956 :     seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
     691      200956 :     page = BufferGetPage(buf);
     692             : 
     693      200956 :     last = next = result = seq->last_value;
     694      200956 :     fetch = cache;
     695      200956 :     log = seq->log_cnt;
     696             : 
     697      200956 :     if (!seq->is_called)
     698             :     {
     699        1156 :         rescnt++;               /* return last_value if not is_called */
     700        1156 :         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      200956 :     if (log < fetch || !seq->is_called)
     714             :     {
     715             :         /* forced log to satisfy local demand for values */
     716        3456 :         fetch = log = fetch + SEQ_LOG_VALS;
     717        3456 :         logit = true;
     718             :     }
     719             :     else
     720             :     {
     721      197500 :         XLogRecPtr  redoptr = GetRedoRecPtr();
     722             : 
     723      197500 :         if (PageGetLSN(page) <= redoptr)
     724             :         {
     725             :             /* last update of seq was before checkpoint */
     726      123232 :             fetch = log = fetch + SEQ_LOG_VALS;
     727      123232 :             logit = true;
     728             :         }
     729             :     }
     730             : 
     731     4453158 :     while (fetch)               /* try to fetch cache [+ log ] numbers */
     732             :     {
     733             :         /*
     734             :          * Check MAXVALUE for ascending sequences and MINVALUE for descending
     735             :          * sequences
     736             :          */
     737     4252260 :         if (incby > 0)
     738             :         {
     739             :             /* ascending sequence */
     740     4251666 :             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     4251626 :                 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     4252202 :         fetch--;
     776     4252202 :         if (rescnt < cache)
     777             :         {
     778      199838 :             log--;
     779      199838 :             rescnt++;
     780      199838 :             last = next;
     781      199838 :             if (rescnt == 1)    /* if it's first result - */
     782      199784 :                 result = next;  /* it's what to return */
     783             :         }
     784             :     }
     785             : 
     786      200940 :     log -= fetch;               /* adjust for any unfetched numbers */
     787             :     Assert(log >= 0);
     788             : 
     789             :     /* save info in local cache */
     790      200940 :     elm->increment = incby;
     791      200940 :     elm->last = result;          /* last returned number */
     792      200940 :     elm->cached = last;          /* last fetched number */
     793      200940 :     elm->last_valid = true;
     794             : 
     795      200940 :     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      200940 :     if (logit && RelationNeedsWAL(seqrel))
     805        3206 :         GetTopTransactionId();
     806             : 
     807             :     /* ready to change the on-disk (or really, in-buffer) tuple */
     808      200940 :     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      200940 :     MarkBufferDirty(buf);
     820             : 
     821             :     /* XLOG stuff */
     822      200940 :     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        3206 :         XLogBeginInsert();
     834        3206 :         XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
     835             : 
     836             :         /* set values that will be saved in xlog */
     837        3206 :         seq->last_value = next;
     838        3206 :         seq->is_called = true;
     839        3206 :         seq->log_cnt = 0;
     840             : 
     841        3206 :         xlrec.locator = seqrel->rd_locator;
     842             : 
     843        3206 :         XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
     844        3206 :         XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
     845             : 
     846        3206 :         recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
     847             : 
     848        3206 :         PageSetLSN(page, recptr);
     849             :     }
     850             : 
     851             :     /* Now update sequence tuple to the intended final state */
     852      200940 :     seq->last_value = last;      /* last fetched number */
     853      200940 :     seq->is_called = true;
     854      200940 :     seq->log_cnt = log;          /* how much is logged */
     855             : 
     856      200940 :     END_CRIT_SECTION();
     857             : 
     858      200940 :     UnlockReleaseBuffer(buf);
     859             : 
     860      200940 :     sequence_close(seqrel, NoLock);
     861             : 
     862      200940 :     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         514 : 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         514 :     init_sequence(relid, &elm, &seqrel);
     959             : 
     960         514 :     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         508 :     pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
     967         508 :     if (!HeapTupleIsValid(pgstuple))
     968           0 :         elog(ERROR, "cache lookup failed for sequence %u", relid);
     969         508 :     pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
     970         508 :     maxv = pgsform->seqmax;
     971         508 :     minv = pgsform->seqmin;
     972         508 :     ReleaseSysCache(pgstuple);
     973             : 
     974             :     /* read-only transactions may only modify temp sequences */
     975         508 :     if (!seqrel->rd_islocaltemp)
     976         250 :         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         502 :     PreventCommandIfParallelMode("setval()");
     984             : 
     985             :     /* lock page buffer and read tuple */
     986         502 :     seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
     987             : 
     988         502 :     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         490 :     if (iscalled)
     997             :     {
     998         184 :         elm->last = next;        /* last returned number */
     999         184 :         elm->last_valid = true;
    1000             :     }
    1001             : 
    1002             :     /* In any case, forget any future cached numbers */
    1003         490 :     elm->cached = elm->last;
    1004             : 
    1005             :     /* check the comment above nextval_internal()'s equivalent call. */
    1006         490 :     if (RelationNeedsWAL(seqrel))
    1007         178 :         GetTopTransactionId();
    1008             : 
    1009             :     /* ready to change the on-disk (or really, in-buffer) tuple */
    1010         490 :     START_CRIT_SECTION();
    1011             : 
    1012         490 :     seq->last_value = next;      /* last fetched number */
    1013         490 :     seq->is_called = iscalled;
    1014         490 :     seq->log_cnt = 0;
    1015             : 
    1016         490 :     MarkBufferDirty(buf);
    1017             : 
    1018             :     /* XLOG stuff */
    1019         490 :     if (RelationNeedsWAL(seqrel))
    1020             :     {
    1021             :         xl_seq_rec  xlrec;
    1022             :         XLogRecPtr  recptr;
    1023         178 :         Page        page = BufferGetPage(buf);
    1024             : 
    1025         178 :         XLogBeginInsert();
    1026         178 :         XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
    1027             : 
    1028         178 :         xlrec.locator = seqrel->rd_locator;
    1029         178 :         XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
    1030         178 :         XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
    1031             : 
    1032         178 :         recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
    1033             : 
    1034         178 :         PageSetLSN(page, recptr);
    1035             :     }
    1036             : 
    1037         490 :     END_CRIT_SECTION();
    1038             : 
    1039         490 :     UnlockReleaseBuffer(buf);
    1040             : 
    1041         490 :     sequence_close(seqrel, NoLock);
    1042         490 : }
    1043             : 
    1044             : /*
    1045             :  * Implement the 2 arg setval procedure.
    1046             :  * See do_setval for discussion.
    1047             :  */
    1048             : Datum
    1049         156 : setval_oid(PG_FUNCTION_ARGS)
    1050             : {
    1051         156 :     Oid         relid = PG_GETARG_OID(0);
    1052         156 :     int64       next = PG_GETARG_INT64(1);
    1053             : 
    1054         156 :     do_setval(relid, next, true);
    1055             : 
    1056         132 :     PG_RETURN_INT64(next);
    1057             : }
    1058             : 
    1059             : /*
    1060             :  * Implement the 3 arg setval procedure.
    1061             :  * See do_setval for discussion.
    1062             :  */
    1063             : Datum
    1064         358 : setval3_oid(PG_FUNCTION_ARGS)
    1065             : {
    1066         358 :     Oid         relid = PG_GETARG_OID(0);
    1067         358 :     int64       next = PG_GETARG_INT64(1);
    1068         358 :     bool        iscalled = PG_GETARG_BOOL(2);
    1069             : 
    1070         358 :     do_setval(relid, next, iscalled);
    1071             : 
    1072         358 :     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      203226 : lock_and_open_sequence(SeqTable seq)
    1086             : {
    1087      203226 :     LocalTransactionId thislxid = MyProc->vxid.lxid;
    1088             : 
    1089             :     /* Get the lock if not already held in this xact */
    1090      203226 :     if (seq->lxid != thislxid)
    1091             :     {
    1092             :         ResourceOwner currentOwner;
    1093             : 
    1094        4998 :         currentOwner = CurrentResourceOwner;
    1095        4998 :         CurrentResourceOwner = TopTransactionResourceOwner;
    1096             : 
    1097        4998 :         LockRelationOid(seq->relid, RowExclusiveLock);
    1098             : 
    1099        4998 :         CurrentResourceOwner = currentOwner;
    1100             : 
    1101             :         /* Flag that we have a lock in the current xact */
    1102        4998 :         seq->lxid = thislxid;
    1103             :     }
    1104             : 
    1105             :     /* We now know we have the lock, and can safely open the rel */
    1106      203226 :     return sequence_open(seq->relid, NoLock);
    1107             : }
    1108             : 
    1109             : /*
    1110             :  * Creates the hash table for storing sequence data
    1111             :  */
    1112             : static void
    1113         620 : create_seq_hashtable(void)
    1114             : {
    1115             :     HASHCTL     ctl;
    1116             : 
    1117         620 :     ctl.keysize = sizeof(Oid);
    1118         620 :     ctl.entrysize = sizeof(SeqTableData);
    1119             : 
    1120         620 :     seqhashtab = hash_create("Sequence values", 16, &ctl,
    1121             :                              HASH_ELEM | HASH_BLOBS);
    1122         620 : }
    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      203190 : 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      203190 :     if (seqhashtab == NULL)
    1137         620 :         create_seq_hashtable();
    1138             : 
    1139      203190 :     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      203190 :     if (!found)
    1150             :     {
    1151             :         /* relid already filled in */
    1152        1914 :         elm->filenumber = InvalidRelFileNumber;
    1153        1914 :         elm->lxid = InvalidLocalTransactionId;
    1154        1914 :         elm->last_valid = false;
    1155        1914 :         elm->last = elm->cached = 0;
    1156             :     }
    1157             : 
    1158             :     /*
    1159             :      * Open the sequence relation.
    1160             :      */
    1161      203190 :     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      203184 :     if (seqrel->rd_rel->relfilenode != elm->filenumber)
    1169             :     {
    1170        2040 :         elm->filenumber = seqrel->rd_rel->relfilenode;
    1171        2040 :         elm->cached = elm->last;
    1172             :     }
    1173             : 
    1174             :     /* Return results */
    1175      203184 :     *p_elm = elm;
    1176      203184 :     *p_rel = seqrel;
    1177      203184 : }
    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      203030 : 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      203030 :     *buf = ReadBuffer(rel, 0);
    1198      203030 :     LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
    1199             : 
    1200      203030 :     page = BufferGetPage(*buf);
    1201      203030 :     sm = (sequence_magic *) PageGetSpecialPointer(page);
    1202             : 
    1203      203030 :     if (sm->magic != SEQ_MAGIC)
    1204           0 :         elog(ERROR, "bad magic number in sequence \"%s\": %08X",
    1205             :              RelationGetRelationName(rel), sm->magic);
    1206             : 
    1207      203030 :     lp = PageGetItemId(page, FirstOffsetNumber);
    1208             :     Assert(ItemIdIsNormal(lp));
    1209             : 
    1210             :     /* Note we currently only bother to set these two fields of *seqdatatuple */
    1211      203030 :     seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
    1212      203030 :     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      203030 :     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      203030 :     seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
    1232             : 
    1233      203030 :     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        3098 : 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        3098 :     DefElem    *as_type = NULL;
    1265        3098 :     DefElem    *start_value = NULL;
    1266        3098 :     DefElem    *restart_value = NULL;
    1267        3098 :     DefElem    *increment_by = NULL;
    1268        3098 :     DefElem    *max_value = NULL;
    1269        3098 :     DefElem    *min_value = NULL;
    1270        3098 :     DefElem    *cache_value = NULL;
    1271        3098 :     DefElem    *is_cycled = NULL;
    1272             :     ListCell   *option;
    1273        3098 :     bool        reset_max_value = false;
    1274        3098 :     bool        reset_min_value = false;
    1275             : 
    1276        3098 :     *need_seq_rewrite = false;
    1277        3098 :     *owned_by = NIL;
    1278             : 
    1279        6620 :     foreach(option, options)
    1280             :     {
    1281        3522 :         DefElem    *defel = (DefElem *) lfirst(option);
    1282             : 
    1283        3522 :         if (strcmp(defel->defname, "as") == 0)
    1284             :         {
    1285        1336 :             if (as_type)
    1286           0 :                 errorConflictingDefElem(defel, pstate);
    1287        1336 :             as_type = defel;
    1288        1336 :             *need_seq_rewrite = true;
    1289             :         }
    1290        2186 :         else if (strcmp(defel->defname, "increment") == 0)
    1291             :         {
    1292         228 :             if (increment_by)
    1293           0 :                 errorConflictingDefElem(defel, pstate);
    1294         228 :             increment_by = defel;
    1295         228 :             *need_seq_rewrite = true;
    1296             :         }
    1297        1958 :         else if (strcmp(defel->defname, "start") == 0)
    1298             :         {
    1299         212 :             if (start_value)
    1300           0 :                 errorConflictingDefElem(defel, pstate);
    1301         212 :             start_value = defel;
    1302         212 :             *need_seq_rewrite = true;
    1303             :         }
    1304        1746 :         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        1662 :         else if (strcmp(defel->defname, "maxvalue") == 0)
    1312             :         {
    1313         160 :             if (max_value)
    1314           0 :                 errorConflictingDefElem(defel, pstate);
    1315         160 :             max_value = defel;
    1316         160 :             *need_seq_rewrite = true;
    1317             :         }
    1318        1502 :         else if (strcmp(defel->defname, "minvalue") == 0)
    1319             :         {
    1320         164 :             if (min_value)
    1321           0 :                 errorConflictingDefElem(defel, pstate);
    1322         164 :             min_value = defel;
    1323         164 :             *need_seq_rewrite = true;
    1324             :         }
    1325        1338 :         else if (strcmp(defel->defname, "cache") == 0)
    1326             :         {
    1327         120 :             if (cache_value)
    1328           0 :                 errorConflictingDefElem(defel, pstate);
    1329         120 :             cache_value = defel;
    1330         120 :             *need_seq_rewrite = true;
    1331             :         }
    1332        1218 :         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        1170 :         else if (strcmp(defel->defname, "owned_by") == 0)
    1340             :         {
    1341        1170 :             if (*owned_by)
    1342           0 :                 errorConflictingDefElem(defel, pstate);
    1343        1170 :             *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.
    1351             :              */
    1352           0 :             ereport(ERROR,
    1353             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    1354             :                      errmsg("invalid sequence option SEQUENCE NAME"),
    1355             :                      parser_errposition(pstate, defel->location)));
    1356             :         }
    1357             :         else
    1358           0 :             elog(ERROR, "option \"%s\" not recognized",
    1359             :                  defel->defname);
    1360             :     }
    1361             : 
    1362             :     /*
    1363             :      * We must reset log_cnt when isInit or when changing any parameters that
    1364             :      * would affect future nextval allocations.
    1365             :      */
    1366        3098 :     if (isInit)
    1367        1736 :         seqdataform->log_cnt = 0;
    1368             : 
    1369             :     /* AS type */
    1370        3098 :     if (as_type != NULL)
    1371             :     {
    1372        1336 :         Oid         newtypid = typenameTypeId(pstate, defGetTypeName(as_type));
    1373             : 
    1374        1330 :         if (newtypid != INT2OID &&
    1375         124 :             newtypid != INT4OID &&
    1376             :             newtypid != INT8OID)
    1377          24 :             ereport(ERROR,
    1378             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1379             :                      for_identity
    1380             :                      ? errmsg("identity column type must be smallint, integer, or bigint")
    1381             :                      : errmsg("sequence type must be smallint, integer, or bigint")));
    1382             : 
    1383        1306 :         if (!isInit)
    1384             :         {
    1385             :             /*
    1386             :              * When changing type and the old sequence min/max values were the
    1387             :              * min/max of the old type, adjust sequence min/max values to
    1388             :              * min/max of new type.  (Otherwise, the user chose explicit
    1389             :              * min/max values, which we'll leave alone.)
    1390             :              */
    1391          90 :             if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX) ||
    1392          66 :                 (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX) ||
    1393          36 :                 (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX))
    1394          66 :                 reset_max_value = true;
    1395          90 :             if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN) ||
    1396          72 :                 (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN) ||
    1397          66 :                 (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN))
    1398          24 :                 reset_min_value = true;
    1399             :         }
    1400             : 
    1401        1306 :         seqform->seqtypid = newtypid;
    1402             :     }
    1403        1762 :     else if (isInit)
    1404             :     {
    1405         496 :         seqform->seqtypid = INT8OID;
    1406             :     }
    1407             : 
    1408             :     /* INCREMENT BY */
    1409        3068 :     if (increment_by != NULL)
    1410             :     {
    1411         228 :         seqform->seqincrement = defGetInt64(increment_by);
    1412         228 :         if (seqform->seqincrement == 0)
    1413           6 :             ereport(ERROR,
    1414             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1415             :                      errmsg("INCREMENT must not be zero")));
    1416         222 :         seqdataform->log_cnt = 0;
    1417             :     }
    1418        2840 :     else if (isInit)
    1419             :     {
    1420        1534 :         seqform->seqincrement = 1;
    1421             :     }
    1422             : 
    1423             :     /* CYCLE */
    1424        3062 :     if (is_cycled != NULL)
    1425             :     {
    1426          48 :         seqform->seqcycle = boolVal(is_cycled->arg);
    1427             :         Assert(BoolIsValid(seqform->seqcycle));
    1428          48 :         seqdataform->log_cnt = 0;
    1429             :     }
    1430        3014 :     else if (isInit)
    1431             :     {
    1432        1690 :         seqform->seqcycle = false;
    1433             :     }
    1434             : 
    1435             :     /* MAXVALUE (null arg means NO MAXVALUE) */
    1436        3062 :     if (max_value != NULL && max_value->arg)
    1437             :     {
    1438          74 :         seqform->seqmax = defGetInt64(max_value);
    1439          74 :         seqdataform->log_cnt = 0;
    1440             :     }
    1441        2988 :     else if (isInit || max_value != NULL || reset_max_value)
    1442             :     {
    1443        1728 :         if (seqform->seqincrement > 0 || reset_max_value)
    1444             :         {
    1445             :             /* ascending seq */
    1446        1692 :             if (seqform->seqtypid == INT2OID)
    1447          74 :                 seqform->seqmax = PG_INT16_MAX;
    1448        1618 :             else if (seqform->seqtypid == INT4OID)
    1449        1070 :                 seqform->seqmax = PG_INT32_MAX;
    1450             :             else
    1451         548 :                 seqform->seqmax = PG_INT64_MAX;
    1452             :         }
    1453             :         else
    1454          36 :             seqform->seqmax = -1;    /* descending seq */
    1455        1728 :         seqdataform->log_cnt = 0;
    1456             :     }
    1457             : 
    1458             :     /* Validate maximum value.  No need to check INT8 as seqmax is an int64 */
    1459        3062 :     if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
    1460        3050 :         || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX)))
    1461          12 :         ereport(ERROR,
    1462             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1463             :                  errmsg("MAXVALUE (%lld) is out of range for sequence data type %s",
    1464             :                         (long long) seqform->seqmax,
    1465             :                         format_type_be(seqform->seqtypid))));
    1466             : 
    1467             :     /* MINVALUE (null arg means NO MINVALUE) */
    1468        3050 :     if (min_value != NULL && min_value->arg)
    1469             :     {
    1470          78 :         seqform->seqmin = defGetInt64(min_value);
    1471          78 :         seqdataform->log_cnt = 0;
    1472             :     }
    1473        2972 :     else if (isInit || min_value != NULL || reset_min_value)
    1474             :     {
    1475        1672 :         if (seqform->seqincrement < 0 || reset_min_value)
    1476             :         {
    1477             :             /* descending seq */
    1478          62 :             if (seqform->seqtypid == INT2OID)
    1479          20 :                 seqform->seqmin = PG_INT16_MIN;
    1480          42 :             else if (seqform->seqtypid == INT4OID)
    1481          28 :                 seqform->seqmin = PG_INT32_MIN;
    1482             :             else
    1483          14 :                 seqform->seqmin = PG_INT64_MIN;
    1484             :         }
    1485             :         else
    1486        1610 :             seqform->seqmin = 1; /* ascending seq */
    1487        1672 :         seqdataform->log_cnt = 0;
    1488             :     }
    1489             : 
    1490             :     /* Validate minimum value.  No need to check INT8 as seqmin is an int64 */
    1491        3050 :     if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
    1492        3038 :         || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX)))
    1493          12 :         ereport(ERROR,
    1494             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1495             :                  errmsg("MINVALUE (%lld) is out of range for sequence data type %s",
    1496             :                         (long long) seqform->seqmin,
    1497             :                         format_type_be(seqform->seqtypid))));
    1498             : 
    1499             :     /* crosscheck min/max */
    1500        3038 :     if (seqform->seqmin >= seqform->seqmax)
    1501          12 :         ereport(ERROR,
    1502             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1503             :                  errmsg("MINVALUE (%lld) must be less than MAXVALUE (%lld)",
    1504             :                         (long long) seqform->seqmin,
    1505             :                         (long long) seqform->seqmax)));
    1506             : 
    1507             :     /* START WITH */
    1508        3026 :     if (start_value != NULL)
    1509             :     {
    1510         212 :         seqform->seqstart = defGetInt64(start_value);
    1511             :     }
    1512        2814 :     else if (isInit)
    1513             :     {
    1514        1504 :         if (seqform->seqincrement > 0)
    1515        1480 :             seqform->seqstart = seqform->seqmin;  /* ascending seq */
    1516             :         else
    1517          24 :             seqform->seqstart = seqform->seqmax;  /* descending seq */
    1518             :     }
    1519             : 
    1520             :     /* crosscheck START */
    1521        3026 :     if (seqform->seqstart < seqform->seqmin)
    1522           6 :         ereport(ERROR,
    1523             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1524             :                  errmsg("START value (%lld) cannot be less than MINVALUE (%lld)",
    1525             :                         (long long) seqform->seqstart,
    1526             :                         (long long) seqform->seqmin)));
    1527        3020 :     if (seqform->seqstart > seqform->seqmax)
    1528           6 :         ereport(ERROR,
    1529             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1530             :                  errmsg("START value (%lld) cannot be greater than MAXVALUE (%lld)",
    1531             :                         (long long) seqform->seqstart,
    1532             :                         (long long) seqform->seqmax)));
    1533             : 
    1534             :     /* RESTART [WITH] */
    1535        3014 :     if (restart_value != NULL)
    1536             :     {
    1537          84 :         if (restart_value->arg != NULL)
    1538          54 :             seqdataform->last_value = defGetInt64(restart_value);
    1539             :         else
    1540          30 :             seqdataform->last_value = seqform->seqstart;
    1541          84 :         seqdataform->is_called = false;
    1542          84 :         seqdataform->log_cnt = 0;
    1543             :     }
    1544        2930 :     else if (isInit)
    1545             :     {
    1546        1670 :         seqdataform->last_value = seqform->seqstart;
    1547        1670 :         seqdataform->is_called = false;
    1548             :     }
    1549             : 
    1550             :     /* crosscheck RESTART (or current value, if changing MIN/MAX) */
    1551        3014 :     if (seqdataform->last_value < seqform->seqmin)
    1552           6 :         ereport(ERROR,
    1553             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1554             :                  errmsg("RESTART value (%lld) cannot be less than MINVALUE (%lld)",
    1555             :                         (long long) seqdataform->last_value,
    1556             :                         (long long) seqform->seqmin)));
    1557        3008 :     if (seqdataform->last_value > seqform->seqmax)
    1558           6 :         ereport(ERROR,
    1559             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1560             :                  errmsg("RESTART value (%lld) cannot be greater than MAXVALUE (%lld)",
    1561             :                         (long long) seqdataform->last_value,
    1562             :                         (long long) seqform->seqmax)));
    1563             : 
    1564             :     /* CACHE */
    1565        3002 :     if (cache_value != NULL)
    1566             :     {
    1567         120 :         seqform->seqcache = defGetInt64(cache_value);
    1568         120 :         if (seqform->seqcache <= 0)
    1569           6 :             ereport(ERROR,
    1570             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1571             :                      errmsg("CACHE (%lld) must be greater than zero",
    1572             :                             (long long) seqform->seqcache)));
    1573         114 :         seqdataform->log_cnt = 0;
    1574             :     }
    1575        2882 :     else if (isInit)
    1576             :     {
    1577        1552 :         seqform->seqcache = 1;
    1578             :     }
    1579        2996 : }
    1580             : 
    1581             : /*
    1582             :  * Process an OWNED BY option for CREATE/ALTER SEQUENCE
    1583             :  *
    1584             :  * Ownership permissions on the sequence are already checked,
    1585             :  * but if we are establishing a new owned-by dependency, we must
    1586             :  * enforce that the referenced table has the same owner and namespace
    1587             :  * as the sequence.
    1588             :  */
    1589             : static void
    1590        1170 : process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
    1591             : {
    1592             :     DependencyType deptype;
    1593             :     int         nnames;
    1594             :     Relation    tablerel;
    1595             :     AttrNumber  attnum;
    1596             : 
    1597        1170 :     deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO;
    1598             : 
    1599        1170 :     nnames = list_length(owned_by);
    1600             :     Assert(nnames > 0);
    1601        1170 :     if (nnames == 1)
    1602             :     {
    1603             :         /* Must be OWNED BY NONE */
    1604          12 :         if (strcmp(strVal(linitial(owned_by)), "none") != 0)
    1605           6 :             ereport(ERROR,
    1606             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    1607             :                      errmsg("invalid OWNED BY option"),
    1608             :                      errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
    1609           6 :         tablerel = NULL;
    1610           6 :         attnum = 0;
    1611             :     }
    1612             :     else
    1613             :     {
    1614             :         List       *relname;
    1615             :         char       *attrname;
    1616             :         RangeVar   *rel;
    1617             : 
    1618             :         /* Separate relname and attr name */
    1619        1158 :         relname = list_copy_head(owned_by, nnames - 1);
    1620        1158 :         attrname = strVal(llast(owned_by));
    1621             : 
    1622             :         /* Open and lock rel to ensure it won't go away meanwhile */
    1623        1158 :         rel = makeRangeVarFromNameList(relname);
    1624        1158 :         tablerel = relation_openrv(rel, AccessShareLock);
    1625             : 
    1626             :         /* Must be a regular or foreign table */
    1627        1158 :         if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
    1628          74 :               tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
    1629          66 :               tablerel->rd_rel->relkind == RELKIND_VIEW ||
    1630          66 :               tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
    1631           6 :             ereport(ERROR,
    1632             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1633             :                      errmsg("sequence cannot be owned by relation \"%s\"",
    1634             :                             RelationGetRelationName(tablerel)),
    1635             :                      errdetail_relkind_not_supported(tablerel->rd_rel->relkind)));
    1636             : 
    1637             :         /* We insist on same owner and schema */
    1638        1152 :         if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
    1639           0 :             ereport(ERROR,
    1640             :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1641             :                      errmsg("sequence must have same owner as table it is linked to")));
    1642        1152 :         if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
    1643           6 :             ereport(ERROR,
    1644             :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    1645             :                      errmsg("sequence must be in same schema as table it is linked to")));
    1646             : 
    1647             :         /* Now, fetch the attribute number from the system cache */
    1648        1146 :         attnum = get_attnum(RelationGetRelid(tablerel), attrname);
    1649        1146 :         if (attnum == InvalidAttrNumber)
    1650           6 :             ereport(ERROR,
    1651             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1652             :                      errmsg("column \"%s\" of relation \"%s\" does not exist",
    1653             :                             attrname, RelationGetRelationName(tablerel))));
    1654             :     }
    1655             : 
    1656             :     /*
    1657             :      * Catch user explicitly running OWNED BY on identity sequence.
    1658             :      */
    1659        1146 :     if (deptype == DEPENDENCY_AUTO)
    1660             :     {
    1661             :         Oid         tableId;
    1662             :         int32       colId;
    1663             : 
    1664         784 :         if (sequenceIsOwned(RelationGetRelid(seqrel), DEPENDENCY_INTERNAL, &tableId, &colId))
    1665           6 :             ereport(ERROR,
    1666             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1667             :                      errmsg("cannot change ownership of identity sequence"),
    1668             :                      errdetail("Sequence \"%s\" is linked to table \"%s\".",
    1669             :                                RelationGetRelationName(seqrel),
    1670             :                                get_rel_name(tableId))));
    1671             :     }
    1672             : 
    1673             :     /*
    1674             :      * OK, we are ready to update pg_depend.  First remove any existing
    1675             :      * dependencies for the sequence, then optionally add a new one.
    1676             :      */
    1677        1140 :     deleteDependencyRecordsForClass(RelationRelationId, RelationGetRelid(seqrel),
    1678             :                                     RelationRelationId, deptype);
    1679             : 
    1680        1140 :     if (tablerel)
    1681             :     {
    1682             :         ObjectAddress refobject,
    1683             :                     depobject;
    1684             : 
    1685        1140 :         refobject.classId = RelationRelationId;
    1686        1140 :         refobject.objectId = RelationGetRelid(tablerel);
    1687        1140 :         refobject.objectSubId = attnum;
    1688        1140 :         depobject.classId = RelationRelationId;
    1689        1140 :         depobject.objectId = RelationGetRelid(seqrel);
    1690        1140 :         depobject.objectSubId = 0;
    1691        1140 :         recordDependencyOn(&depobject, &refobject, deptype);
    1692             :     }
    1693             : 
    1694             :     /* Done, but hold lock until commit */
    1695        1140 :     if (tablerel)
    1696        1140 :         relation_close(tablerel, NoLock);
    1697        1140 : }
    1698             : 
    1699             : 
    1700             : /*
    1701             :  * Return sequence parameters in a list of the form created by the parser.
    1702             :  */
    1703             : List *
    1704          12 : sequence_options(Oid relid)
    1705             : {
    1706             :     HeapTuple   pgstuple;
    1707             :     Form_pg_sequence pgsform;
    1708          12 :     List       *options = NIL;
    1709             : 
    1710          12 :     pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
    1711          12 :     if (!HeapTupleIsValid(pgstuple))
    1712           0 :         elog(ERROR, "cache lookup failed for sequence %u", relid);
    1713          12 :     pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
    1714             : 
    1715             :     /* Use makeFloat() for 64-bit integers, like gram.y does. */
    1716          12 :     options = lappend(options,
    1717          12 :                       makeDefElem("cache", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1));
    1718          12 :     options = lappend(options,
    1719          12 :                       makeDefElem("cycle", (Node *) makeBoolean(pgsform->seqcycle), -1));
    1720          12 :     options = lappend(options,
    1721          12 :                       makeDefElem("increment", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1));
    1722          12 :     options = lappend(options,
    1723          12 :                       makeDefElem("maxvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmax)), -1));
    1724          12 :     options = lappend(options,
    1725          12 :                       makeDefElem("minvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmin)), -1));
    1726          12 :     options = lappend(options,
    1727          12 :                       makeDefElem("start", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqstart)), -1));
    1728             : 
    1729          12 :     ReleaseSysCache(pgstuple);
    1730             : 
    1731          12 :     return options;
    1732             : }
    1733             : 
    1734             : /*
    1735             :  * Return sequence parameters (formerly for use by information schema)
    1736             :  */
    1737             : Datum
    1738           6 : pg_sequence_parameters(PG_FUNCTION_ARGS)
    1739             : {
    1740           6 :     Oid         relid = PG_GETARG_OID(0);
    1741             :     TupleDesc   tupdesc;
    1742             :     Datum       values[7];
    1743             :     bool        isnull[7];
    1744             :     HeapTuple   pgstuple;
    1745             :     Form_pg_sequence pgsform;
    1746             : 
    1747           6 :     if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
    1748           0 :         ereport(ERROR,
    1749             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    1750             :                  errmsg("permission denied for sequence %s",
    1751             :                         get_rel_name(relid))));
    1752             : 
    1753           6 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
    1754           0 :         elog(ERROR, "return type must be a row type");
    1755             : 
    1756           6 :     memset(isnull, 0, sizeof(isnull));
    1757             : 
    1758           6 :     pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
    1759           6 :     if (!HeapTupleIsValid(pgstuple))
    1760           0 :         elog(ERROR, "cache lookup failed for sequence %u", relid);
    1761           6 :     pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
    1762             : 
    1763           6 :     values[0] = Int64GetDatum(pgsform->seqstart);
    1764           6 :     values[1] = Int64GetDatum(pgsform->seqmin);
    1765           6 :     values[2] = Int64GetDatum(pgsform->seqmax);
    1766           6 :     values[3] = Int64GetDatum(pgsform->seqincrement);
    1767           6 :     values[4] = BoolGetDatum(pgsform->seqcycle);
    1768           6 :     values[5] = Int64GetDatum(pgsform->seqcache);
    1769           6 :     values[6] = ObjectIdGetDatum(pgsform->seqtypid);
    1770             : 
    1771           6 :     ReleaseSysCache(pgstuple);
    1772             : 
    1773           6 :     return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
    1774             : }
    1775             : 
    1776             : /*
    1777             :  * Return the last value from the sequence
    1778             :  *
    1779             :  * Note: This has a completely different meaning than lastval().
    1780             :  */
    1781             : Datum
    1782         116 : pg_sequence_last_value(PG_FUNCTION_ARGS)
    1783             : {
    1784         116 :     Oid         relid = PG_GETARG_OID(0);
    1785             :     SeqTable    elm;
    1786             :     Relation    seqrel;
    1787         116 :     bool        is_called = false;
    1788         116 :     int64       result = 0;
    1789             : 
    1790             :     /* open and lock sequence */
    1791         116 :     init_sequence(relid, &elm, &seqrel);
    1792             : 
    1793             :     /*
    1794             :      * We return NULL for other sessions' temporary sequences.  The
    1795             :      * pg_sequences system view already filters those out, but this offers a
    1796             :      * defense against ERRORs in case someone invokes this function directly.
    1797             :      *
    1798             :      * Also, for the benefit of the pg_sequences view, we return NULL for
    1799             :      * unlogged sequences on standbys and for sequences for which the current
    1800             :      * user lacks privileges instead of throwing an error.
    1801             :      */
    1802         116 :     if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_USAGE) == ACLCHECK_OK &&
    1803         116 :         !RELATION_IS_OTHER_TEMP(seqrel) &&
    1804         116 :         (RelationIsPermanent(seqrel) || !RecoveryInProgress()))
    1805             :     {
    1806             :         Buffer      buf;
    1807             :         HeapTupleData seqtuple;
    1808             :         Form_pg_sequence_data seq;
    1809             : 
    1810         114 :         seq = read_seq_tuple(seqrel, &buf, &seqtuple);
    1811             : 
    1812         114 :         is_called = seq->is_called;
    1813         114 :         result = seq->last_value;
    1814             : 
    1815         114 :         UnlockReleaseBuffer(buf);
    1816             :     }
    1817         116 :     sequence_close(seqrel, NoLock);
    1818             : 
    1819         116 :     if (is_called)
    1820          48 :         PG_RETURN_INT64(result);
    1821             :     else
    1822          68 :         PG_RETURN_NULL();
    1823             : }
    1824             : 
    1825             : 
    1826             : void
    1827        4596 : seq_redo(XLogReaderState *record)
    1828             : {
    1829        4596 :     XLogRecPtr  lsn = record->EndRecPtr;
    1830        4596 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
    1831             :     Buffer      buffer;
    1832             :     Page        page;
    1833             :     Page        localpage;
    1834             :     char       *item;
    1835             :     Size        itemsz;
    1836        4596 :     xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
    1837             :     sequence_magic *sm;
    1838             : 
    1839        4596 :     if (info != XLOG_SEQ_LOG)
    1840           0 :         elog(PANIC, "seq_redo: unknown op code %u", info);
    1841             : 
    1842        4596 :     buffer = XLogInitBufferForRedo(record, 0);
    1843        4596 :     page = (Page) BufferGetPage(buffer);
    1844             : 
    1845             :     /*
    1846             :      * We always reinit the page.  However, since this WAL record type is also
    1847             :      * used for updating sequences, it's possible that a hot-standby backend
    1848             :      * is examining the page concurrently; so we mustn't transiently trash the
    1849             :      * buffer.  The solution is to build the correct new page contents in
    1850             :      * local workspace and then memcpy into the buffer.  Then only bytes that
    1851             :      * are supposed to change will change, even transiently. We must palloc
    1852             :      * the local page for alignment reasons.
    1853             :      */
    1854        4596 :     localpage = (Page) palloc(BufferGetPageSize(buffer));
    1855             : 
    1856        4596 :     PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
    1857        4596 :     sm = (sequence_magic *) PageGetSpecialPointer(localpage);
    1858        4596 :     sm->magic = SEQ_MAGIC;
    1859             : 
    1860        4596 :     item = (char *) xlrec + sizeof(xl_seq_rec);
    1861        4596 :     itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
    1862             : 
    1863        4596 :     if (PageAddItem(localpage, (Item) item, itemsz,
    1864             :                     FirstOffsetNumber, false, false) == InvalidOffsetNumber)
    1865           0 :         elog(PANIC, "seq_redo: failed to add item to page");
    1866             : 
    1867        4596 :     PageSetLSN(localpage, lsn);
    1868             : 
    1869        4596 :     memcpy(page, localpage, BufferGetPageSize(buffer));
    1870        4596 :     MarkBufferDirty(buffer);
    1871        4596 :     UnlockReleaseBuffer(buffer);
    1872             : 
    1873        4596 :     pfree(localpage);
    1874        4596 : }
    1875             : 
    1876             : /*
    1877             :  * Flush cached sequence information.
    1878             :  */
    1879             : void
    1880          18 : ResetSequenceCaches(void)
    1881             : {
    1882          18 :     if (seqhashtab)
    1883             :     {
    1884          12 :         hash_destroy(seqhashtab);
    1885          12 :         seqhashtab = NULL;
    1886             :     }
    1887             : 
    1888          18 :     last_used_seq = NULL;
    1889          18 : }
    1890             : 
    1891             : /*
    1892             :  * Mask a Sequence page before performing consistency checks on it.
    1893             :  */
    1894             : void
    1895           0 : seq_mask(char *page, BlockNumber blkno)
    1896             : {
    1897           0 :     mask_page_lsn_and_checksum(page);
    1898             : 
    1899           0 :     mask_unused_space(page);
    1900           0 : }

Generated by: LCOV version 1.14