LCOV - differential code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 94.7 % 701 664 1 3 14 19 13 210 14 427 3 213 2 21
Current Date: 2023-04-08 17:13:01 Functions: 96.3 % 27 26 1 18 5 3 1 18
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (60,120] days: 50.0 % 2 1 1 1
(240..) days: 94.8 % 698 662 3 14 19 13 210 12 427 3 213
Function coverage date bins:
(240..) days: 56.5 % 46 26 1 18 5 3 1 18

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

Generated by: LCOV version v1.16-55-g56c0a2a