LCOV - differential code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 95.5 % 719 687 32 25 662 18
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 28 28 4 24
Baseline: lcov-20250906-005545-baseline Branches: 74.9 % 554 415 139 6 409
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 25 25 25
(30,360] days: 100.0 % 6 6 6
(360..) days: 95.3 % 688 656 32 656
Function coverage date bins:
(360..) days: 100.0 % 28 28 4 24
Branch coverage date bins:
(7,30] days: 100.0 % 6 6 6
(360..) days: 74.6 % 548 409 139 409

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

Generated by: LCOV version 2.4-beta