LCOV - differential code coverage report
Current view: top level - src/backend/commands - sequence.c (source / functions) Coverage Total Hit UBC GNC CBC DUB DCB
Current: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 95.7 % 696 666 30 31 635 2 45
Current Date: 2025-12-15 18:36:29 -0500 Functions: 100.0 % 26 26 8 18 3
Baseline: lcov-20251216-010103-baseline Branches: 75.6 % 546 413 133 6 407
Baseline Date: 2025-12-15 13:30:48 -0800 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 37 37 31 6
(360..) days: 95.4 % 659 629 30 629
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 100.0 % 25 25 7 18
Branch coverage date bins:
(30,360] days: 100.0 % 6 6 6
(360..) days: 75.4 % 540 407 133 407

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

Generated by: LCOV version 2.4-beta