LCOV - differential code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 94.6 % 686 649 37 24 625 39
Current Date: 2024-04-14 14:21:10 Functions: 96.3 % 27 26 1 14 12
Baseline: 16@8cea358b128 Branches: 74.8 % 540 404 136 404
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 16 16 16
(180,240] days: 100.0 % 7 7 6 1
(240..) days: 94.4 % 663 626 37 2 624
Function coverage date bins:
(240..) days: 96.3 % 27 26 1 14 12
Branch coverage date bins:
(240..) days: 74.8 % 540 404 136 404

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

Generated by: LCOV version 2.1-beta2-3-g6141622