Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions

sequence.h File Reference

#include "access/xlog.h"
#include "fmgr.h"
#include "nodes/parsenodes.h"
#include "storage/relfilenode.h"
Include dependency graph for sequence.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  FormData_pg_sequence
struct  xl_seq_rec

Defines

#define SEQ_COL_NAME   1
#define SEQ_COL_LASTVAL   2
#define SEQ_COL_STARTVAL   3
#define SEQ_COL_INCBY   4
#define SEQ_COL_MAXVALUE   5
#define SEQ_COL_MINVALUE   6
#define SEQ_COL_CACHE   7
#define SEQ_COL_LOG   8
#define SEQ_COL_CYCLE   9
#define SEQ_COL_CALLED   10
#define SEQ_COL_FIRSTCOL   SEQ_COL_NAME
#define SEQ_COL_LASTCOL   SEQ_COL_CALLED
#define XLOG_SEQ_LOG   0x00

Typedefs

typedef struct FormData_pg_sequence FormData_pg_sequence
typedef FormData_pg_sequenceForm_pg_sequence
typedef struct xl_seq_rec xl_seq_rec

Functions

Datum nextval (PG_FUNCTION_ARGS)
Datum nextval_oid (PG_FUNCTION_ARGS)
Datum currval_oid (PG_FUNCTION_ARGS)
Datum setval_oid (PG_FUNCTION_ARGS)
Datum setval3_oid (PG_FUNCTION_ARGS)
Datum lastval (PG_FUNCTION_ARGS)
Datum pg_sequence_parameters (PG_FUNCTION_ARGS)
Oid DefineSequence (CreateSeqStmt *stmt)
Oid AlterSequence (AlterSeqStmt *stmt)
void ResetSequence (Oid seq_relid)
void seq_redo (XLogRecPtr lsn, XLogRecord *rptr)
void seq_desc (StringInfo buf, uint8 xl_info, char *rec)

Define Documentation

#define SEQ_COL_CACHE   7

Definition at line 48 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_CALLED   10

Definition at line 51 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_CYCLE   9

Definition at line 50 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_FIRSTCOL   SEQ_COL_NAME

Definition at line 53 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_INCBY   4

Definition at line 45 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_LASTCOL   SEQ_COL_CALLED

Definition at line 54 of file sequence.h.

#define SEQ_COL_LASTVAL   2

Definition at line 43 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_LOG   8

Definition at line 49 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_MAXVALUE   5

Definition at line 46 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_MINVALUE   6

Definition at line 47 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_NAME   1

Definition at line 42 of file sequence.h.

Referenced by DefineSequence().

#define SEQ_COL_STARTVAL   3

Definition at line 44 of file sequence.h.

Referenced by DefineSequence().

#define XLOG_SEQ_LOG   0x00

Typedef Documentation

Definition at line 36 of file sequence.h.

typedef struct xl_seq_rec xl_seq_rec

Function Documentation

Oid AlterSequence ( AlterSeqStmt stmt  ) 

Definition at line 409 of file sequence.c.

References AccessShareLock, ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, buf, XLogRecData::buffer, BufferGetPage, SeqTableData::cached, XLogRecData::data, END_CRIT_SECTION, ereport, errmsg(), GetUserId(), init_params(), init_sequence(), InvalidBuffer, InvalidOid, InvokeObjectPostAlterHook, SeqTableData::last, XLogRecData::len, MarkBufferDirty(), AlterSeqStmt::missing_ok, XLogRecData::next, xl_seq_rec::node, NoLock, NOTICE, NULL, AlterSeqStmt::options, PageSetLSN, pg_class_ownercheck(), process_owned_by(), RangeVarGetRelid, RelationData::rd_node, read_seq_tuple(), relation_close(), RelationNeedsWAL, RelationRelationId, SeqTableData::relid, RangeVar::relname, AlterSeqStmt::sequence, START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, and XLogInsert().

Referenced by ProcessUtilitySlow().

{
    Oid         relid;
    SeqTable    elm;
    Relation    seqrel;
    Buffer      buf;
    HeapTupleData seqtuple;
    Form_pg_sequence seq;
    FormData_pg_sequence new;
    List       *owned_by;

    /* Open and lock sequence. */
    relid = RangeVarGetRelid(stmt->sequence, AccessShareLock, stmt->missing_ok);
    if (relid == InvalidOid)
    {
        ereport(NOTICE,
                (errmsg("relation \"%s\" does not exist, skipping",
                        stmt->sequence->relname)));
        return InvalidOid;
    }

    init_sequence(relid, &elm, &seqrel);

    /* allow ALTER to sequence owner only */
    if (!pg_class_ownercheck(relid, GetUserId()))
        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
                       stmt->sequence->relname);

    /* lock page' buffer and read tuple into new sequence structure */
    seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);

    /* Copy old values of options into workspace */
    memcpy(&new, seq, sizeof(FormData_pg_sequence));

    /* Check and set new values */
    init_params(stmt->options, false, &new, &owned_by);

    /* Clear local cache so that we don't think we have cached numbers */
    /* Note that we do not change the currval() state */
    elm->cached = elm->last;

    /* Now okay to update the on-disk tuple */
    START_CRIT_SECTION();

    memcpy(seq, &new, sizeof(FormData_pg_sequence));

    MarkBufferDirty(buf);

    /* XLOG stuff */
    if (RelationNeedsWAL(seqrel))
    {
        xl_seq_rec  xlrec;
        XLogRecPtr  recptr;
        XLogRecData rdata[2];
        Page        page = BufferGetPage(buf);

        xlrec.node = seqrel->rd_node;
        rdata[0].data = (char *) &xlrec;
        rdata[0].len = sizeof(xl_seq_rec);
        rdata[0].buffer = InvalidBuffer;
        rdata[0].next = &(rdata[1]);

        rdata[1].data = (char *) seqtuple.t_data;
        rdata[1].len = seqtuple.t_len;
        rdata[1].buffer = InvalidBuffer;
        rdata[1].next = NULL;

        recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG, rdata);

        PageSetLSN(page, recptr);
    }

    END_CRIT_SECTION();

    UnlockReleaseBuffer(buf);

    /* process OWNED BY if given */
    if (owned_by)
        process_owned_by(seqrel, owned_by);

    InvokeObjectPostAlterHook(RelationRelationId, relid, 0);

    relation_close(seqrel, NoLock);

    return relid;
}

Datum currval_oid ( PG_FUNCTION_ARGS   ) 

Definition at line 759 of file sequence.c.

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, GetUserId(), init_sequence(), SeqTableData::last, SeqTableData::last_valid, NoLock, pg_class_aclcheck(), PG_GETARG_OID, PG_RETURN_INT64, relation_close(), RelationGetRelationName, and SeqTableData::relid.

{
    Oid         relid = PG_GETARG_OID(0);
    int64       result;
    SeqTable    elm;
    Relation    seqrel;

    /* open and AccessShareLock sequence */
    init_sequence(relid, &elm, &seqrel);

    if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
        pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
        ereport(ERROR,
                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                 errmsg("permission denied for sequence %s",
                        RelationGetRelationName(seqrel))));

    if (!elm->last_valid)
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("currval of sequence \"%s\" is not yet defined in this session",
                        RelationGetRelationName(seqrel))));

    result = elm->last;

    relation_close(seqrel, NoLock);

    PG_RETURN_INT64(result);
}

Oid DefineSequence ( CreateSeqStmt stmt  ) 

Definition at line 109 of file sequence.c.

References AccessExclusiveLock, Assert, BoolGetDatum, BOOLOID, ColumnDef::collClause, ColumnDef::collOid, ColumnDef::colname, CreateStmt::constraints, ColumnDef::constraints, ColumnDef::cooked_default, DefineRelation(), ereport, errcode(), errmsg(), ERROR, fill_seq_with_data(), heap_close, heap_form_tuple(), heap_open(), i, CreateStmt::if_not_exists, ColumnDef::inhcount, CreateStmt::inhRelations, init_params(), Int64GetDatum(), Int64GetDatumFast, INT8OID, InvalidOid, ColumnDef::is_from_type, ColumnDef::is_local, ColumnDef::is_not_null, lappend(), makeNode, makeTypeNameFromOid(), name, NameGetDatum, NAMEOID, namestrcpy(), NoLock, CreateStmt::oncommit, CreateStmt::options, CreateSeqStmt::options, CreateSeqStmt::ownerId, process_owned_by(), ColumnDef::raw_default, CreateStmt::relation, RelationGetDescr, RELKIND_SEQUENCE, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_UNLOGGED, SEQ_COL_CACHE, SEQ_COL_CALLED, SEQ_COL_CYCLE, SEQ_COL_FIRSTCOL, SEQ_COL_INCBY, SEQ_COL_LASTVAL, SEQ_COL_LOG, SEQ_COL_MAXVALUE, SEQ_COL_MINVALUE, SEQ_COL_NAME, SEQ_COL_STARTVAL, CreateSeqStmt::sequence, ColumnDef::storage, CreateStmt::tableElts, CreateStmt::tablespacename, ColumnDef::typeName, and value.

Referenced by ProcessUtilitySlow().

{
    FormData_pg_sequence new;
    List       *owned_by;
    CreateStmt *stmt = makeNode(CreateStmt);
    Oid         seqoid;
    Relation    rel;
    HeapTuple   tuple;
    TupleDesc   tupDesc;
    Datum       value[SEQ_COL_LASTCOL];
    bool        null[SEQ_COL_LASTCOL];
    int         i;
    NameData    name;

    /* Unlogged sequences are not implemented -- not clear if useful. */
    if (seq->sequence->relpersistence == RELPERSISTENCE_UNLOGGED)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("unlogged sequences are not supported")));

    /* Check and set all option values */
    init_params(seq->options, true, &new, &owned_by);

    /*
     * Create relation (and fill value[] and null[] for the tuple)
     */
    stmt->tableElts = NIL;
    for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
    {
        ColumnDef  *coldef = makeNode(ColumnDef);

        coldef->inhcount = 0;
        coldef->is_local = true;
        coldef->is_not_null = true;
        coldef->is_from_type = false;
        coldef->storage = 0;
        coldef->raw_default = NULL;
        coldef->cooked_default = NULL;
        coldef->collClause = NULL;
        coldef->collOid = InvalidOid;
        coldef->constraints = NIL;

        null[i - 1] = false;

        switch (i)
        {
            case SEQ_COL_NAME:
                coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
                coldef->colname = "sequence_name";
                namestrcpy(&name, seq->sequence->relname);
                value[i - 1] = NameGetDatum(&name);
                break;
            case SEQ_COL_LASTVAL:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "last_value";
                value[i - 1] = Int64GetDatumFast(new.last_value);
                break;
            case SEQ_COL_STARTVAL:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "start_value";
                value[i - 1] = Int64GetDatumFast(new.start_value);
                break;
            case SEQ_COL_INCBY:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "increment_by";
                value[i - 1] = Int64GetDatumFast(new.increment_by);
                break;
            case SEQ_COL_MAXVALUE:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "max_value";
                value[i - 1] = Int64GetDatumFast(new.max_value);
                break;
            case SEQ_COL_MINVALUE:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "min_value";
                value[i - 1] = Int64GetDatumFast(new.min_value);
                break;
            case SEQ_COL_CACHE:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "cache_value";
                value[i - 1] = Int64GetDatumFast(new.cache_value);
                break;
            case SEQ_COL_LOG:
                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                coldef->colname = "log_cnt";
                value[i - 1] = Int64GetDatum((int64) 0);
                break;
            case SEQ_COL_CYCLE:
                coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
                coldef->colname = "is_cycled";
                value[i - 1] = BoolGetDatum(new.is_cycled);
                break;
            case SEQ_COL_CALLED:
                coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
                coldef->colname = "is_called";
                value[i - 1] = BoolGetDatum(false);
                break;
        }
        stmt->tableElts = lappend(stmt->tableElts, coldef);
    }

    stmt->relation = seq->sequence;
    stmt->inhRelations = NIL;
    stmt->constraints = NIL;
    stmt->options = NIL;
    stmt->oncommit = ONCOMMIT_NOOP;
    stmt->tablespacename = NULL;
    stmt->if_not_exists = false;

    seqoid = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId);
    Assert(seqoid != InvalidOid);

    rel = heap_open(seqoid, AccessExclusiveLock);
    tupDesc = RelationGetDescr(rel);

    /* now initialize the sequence's data */
    tuple = heap_form_tuple(tupDesc, value, null);
    fill_seq_with_data(rel, tuple);

    /* process OWNED BY if given */
    if (owned_by)
        process_owned_by(rel, owned_by);

    heap_close(rel, NoLock);

    return seqoid;
}

Datum lastval ( PG_FUNCTION_ARGS   ) 

Definition at line 790 of file sequence.c.

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, Assert, ereport, errcode(), errmsg(), ERROR, GetUserId(), SeqTableData::last, SeqTableData::last_valid, NoLock, NULL, ObjectIdGetDatum, open_share_lock(), pg_class_aclcheck(), PG_RETURN_INT64, relation_close(), RelationGetRelationName, SeqTableData::relid, RELOID, and SearchSysCacheExists1.

{
    Relation    seqrel;
    int64       result;

    if (last_used_seq == NULL)
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("lastval is not yet defined in this session")));

    /* Someone may have dropped the sequence since the last nextval() */
    if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(last_used_seq->relid)))
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("lastval is not yet defined in this session")));

    seqrel = open_share_lock(last_used_seq);

    /* nextval() must have already been called for this sequence */
    Assert(last_used_seq->last_valid);

    if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
        pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
        ereport(ERROR,
                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                 errmsg("permission denied for sequence %s",
                        RelationGetRelationName(seqrel))));

    result = last_used_seq->last;
    relation_close(seqrel, NoLock);

    PG_RETURN_INT64(result);
}

Datum nextval ( PG_FUNCTION_ARGS   ) 

Definition at line 503 of file sequence.c.

References makeRangeVarFromNameList(), nextval_internal(), NoLock, PG_GETARG_TEXT_P, PG_RETURN_INT64, RangeVarGetRelid, SeqTableData::relid, and textToQualifiedNameList().

Referenced by autoinc(), and ttdummy().

{
    text       *seqin = PG_GETARG_TEXT_P(0);
    RangeVar   *sequence;
    Oid         relid;

    sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));

    /*
     * XXX: This is not safe in the presence of concurrent DDL, but acquiring
     * a lock here is more expensive than letting nextval_internal do it,
     * since the latter maintains a cache that keeps us from hitting the lock
     * manager more than once per transaction.  It's not clear whether the
     * performance penalty is material in practice, but for now, we do it this
     * way.
     */
    relid = RangeVarGetRelid(sequence, NoLock, false);

    PG_RETURN_INT64(nextval_internal(relid));
}

Datum nextval_oid ( PG_FUNCTION_ARGS   ) 
Datum pg_sequence_parameters ( PG_FUNCTION_ARGS   ) 

Definition at line 1499 of file sequence.c.

References ACL_SELECT, ACL_UPDATE, ACL_USAGE, ACLCHECK_OK, BlessTupleDesc(), BoolGetDatum, BOOLOID, buf, CreateTemplateTupleDesc(), ereport, errcode(), errmsg(), ERROR, GetUserId(), heap_form_tuple(), HeapTupleGetDatum, FormData_pg_sequence::increment_by, init_sequence(), Int64GetDatum(), INT8OID, FormData_pg_sequence::is_cycled, FormData_pg_sequence::max_value, FormData_pg_sequence::min_value, NoLock, pg_class_aclcheck(), PG_GETARG_OID, read_seq_tuple(), relation_close(), RelationGetRelationName, SeqTableData::relid, FormData_pg_sequence::start_value, TupleDescInitEntry(), UnlockReleaseBuffer(), and values.

{
    Oid         relid = PG_GETARG_OID(0);
    TupleDesc   tupdesc;
    Datum       values[5];
    bool        isnull[5];
    SeqTable    elm;
    Relation    seqrel;
    Buffer      buf;
    HeapTupleData seqtuple;
    Form_pg_sequence seq;

    /* open and AccessShareLock sequence */
    init_sequence(relid, &elm, &seqrel);

    if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
        ereport(ERROR,
                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                 errmsg("permission denied for sequence %s",
                        RelationGetRelationName(seqrel))));

    tupdesc = CreateTemplateTupleDesc(5, false);
    TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
                       INT8OID, -1, 0);
    TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
                       INT8OID, -1, 0);
    TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
                       INT8OID, -1, 0);
    TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
                       INT8OID, -1, 0);
    TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
                       BOOLOID, -1, 0);

    BlessTupleDesc(tupdesc);

    memset(isnull, 0, sizeof(isnull));

    seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);

    values[0] = Int64GetDatum(seq->start_value);
    values[1] = Int64GetDatum(seq->min_value);
    values[2] = Int64GetDatum(seq->max_value);
    values[3] = Int64GetDatum(seq->increment_by);
    values[4] = BoolGetDatum(seq->is_cycled);

    UnlockReleaseBuffer(buf);
    relation_close(seqrel, NoLock);

    return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
}

void ResetSequence ( Oid  seq_relid  ) 

Definition at line 250 of file sequence.c.

References buf, SeqTableData::cached, fill_seq_with_data(), GETSTRUCT, heap_copytuple(), init_sequence(), InvalidMultiXactId, InvalidTransactionId, FormData_pg_sequence::is_called, SeqTableData::last, FormData_pg_sequence::last_value, FormData_pg_sequence::log_cnt, NoLock, read_seq_tuple(), relation_close(), RelationSetNewRelfilenode(), FormData_pg_sequence::start_value, and UnlockReleaseBuffer().

Referenced by ExecuteTruncate().

{
    Relation    seq_rel;
    SeqTable    elm;
    Form_pg_sequence seq;
    Buffer      buf;
    HeapTupleData seqtuple;
    HeapTuple   tuple;

    /*
     * Read the old sequence.  This does a bit more work than really
     * necessary, but it's simple, and we do want to double-check that it's
     * indeed a sequence.
     */
    init_sequence(seq_relid, &elm, &seq_rel);
    (void) read_seq_tuple(elm, seq_rel, &buf, &seqtuple);

    /*
     * Copy the existing sequence tuple.
     */
    tuple = heap_copytuple(&seqtuple);

    /* Now we're done with the old page */
    UnlockReleaseBuffer(buf);

    /*
     * Modify the copied tuple to execute the restart (compare the RESTART
     * action in AlterSequence)
     */
    seq = (Form_pg_sequence) GETSTRUCT(tuple);
    seq->last_value = seq->start_value;
    seq->is_called = false;
    seq->log_cnt = 0;

    /*
     * Create a new storage file for the sequence.  We want to keep the
     * sequence's relfrozenxid at 0, since it won't contain any unfrozen XIDs.
     * Same with relminmxid, since a sequence will never contain multixacts.
     */
    RelationSetNewRelfilenode(seq_rel, InvalidTransactionId,
                              InvalidMultiXactId);

    /*
     * Insert the modified tuple into the new storage file.
     */
    fill_seq_with_data(seq_rel, tuple);

    /* Clear local cache so that we don't think we have cached numbers */
    /* Note that we do not change the currval() state */
    elm->cached = elm->last;

    relation_close(seq_rel, NoLock);
}

void seq_desc ( StringInfo  buf,
uint8  xl_info,
char *  rec 
)

Definition at line 21 of file seqdesc.c.

References appendStringInfo(), RelFileNode::dbNode, xl_seq_rec::node, RelFileNode::relNode, RelFileNode::spcNode, and XLOG_SEQ_LOG.

{
    uint8       info = xl_info & ~XLR_INFO_MASK;
    xl_seq_rec *xlrec = (xl_seq_rec *) rec;

    if (info == XLOG_SEQ_LOG)
        appendStringInfo(buf, "log: ");
    else
    {
        appendStringInfo(buf, "UNKNOWN");
        return;
    }

    appendStringInfo(buf, "rel %u/%u/%u",
               xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode);
}

void seq_redo ( XLogRecPtr  lsn,
XLogRecord rptr 
)

Definition at line 1552 of file sequence.c.

References Assert, BufferGetPage, BufferGetPageSize, BufferIsValid, elog, InvalidOffsetNumber, sequence_magic::magic, MarkBufferDirty(), xl_seq_rec::node, PageAddItem(), PageGetSpecialPointer, PageInit(), PageSetLSN, palloc(), PANIC, pfree(), UnlockReleaseBuffer(), XLogRecord::xl_info, XLogRecord::xl_len, XLOG_SEQ_LOG, XLogReadBuffer(), XLogRecGetData, and XLR_BKP_BLOCK_MASK.

{
    uint8       info = record->xl_info & ~XLR_INFO_MASK;
    Buffer      buffer;
    Page        page;
    Page        localpage;
    char       *item;
    Size        itemsz;
    xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
    sequence_magic *sm;

    /* Backup blocks are not used in seq records */
    Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));

    if (info != XLOG_SEQ_LOG)
        elog(PANIC, "seq_redo: unknown op code %u", info);

    buffer = XLogReadBuffer(xlrec->node, 0, true);
    Assert(BufferIsValid(buffer));
    page = (Page) BufferGetPage(buffer);

    /*
     * We must always reinit the page and reinstall the magic number (see
     * comments in fill_seq_with_data).  However, since this WAL record type
     * is also used for updating sequences, it's possible that a hot-standby
     * backend is examining the page concurrently; so we mustn't transiently
     * trash the buffer.  The solution is to build the correct new page
     * contents in local workspace and then memcpy into the buffer.  Then only
     * bytes that are supposed to change will change, even transiently. We
     * must palloc the local page for alignment reasons.
     */
    localpage = (Page) palloc(BufferGetPageSize(buffer));

    PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
    sm = (sequence_magic *) PageGetSpecialPointer(localpage);
    sm->magic = SEQ_MAGIC;

    item = (char *) xlrec + sizeof(xl_seq_rec);
    itemsz = record->xl_len - sizeof(xl_seq_rec);

    if (PageAddItem(localpage, (Item) item, itemsz,
                    FirstOffsetNumber, false, false) == InvalidOffsetNumber)
        elog(PANIC, "seq_redo: failed to add item to page");

    PageSetLSN(localpage, lsn);

    memcpy(page, localpage, BufferGetPageSize(buffer));
    MarkBufferDirty(buffer);
    UnlockReleaseBuffer(buffer);

    pfree(localpage);
}

Datum setval3_oid ( PG_FUNCTION_ARGS   ) 

Definition at line 948 of file sequence.c.

References do_setval(), next(), PG_GETARG_BOOL, PG_GETARG_INT64, PG_GETARG_OID, PG_RETURN_INT64, and SeqTableData::relid.

{
    Oid         relid = PG_GETARG_OID(0);
    int64       next = PG_GETARG_INT64(1);
    bool        iscalled = PG_GETARG_BOOL(2);

    do_setval(relid, next, iscalled);

    PG_RETURN_INT64(next);
}

Datum setval_oid ( PG_FUNCTION_ARGS   ) 

Definition at line 933 of file sequence.c.

References do_setval(), next(), PG_GETARG_INT64, PG_GETARG_OID, PG_RETURN_INT64, and SeqTableData::relid.

{
    Oid         relid = PG_GETARG_OID(0);
    int64       next = PG_GETARG_INT64(1);

    do_setval(relid, next, true);

    PG_RETURN_INT64(next);
}