LCOV - code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 660 696 94.8 %
Date: 2020-06-01 09:07:10 Functions: 24 25 96.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13