#include "access/xlog.h"
#include "fmgr.h"
#include "nodes/parsenodes.h"
#include "storage/relfilenode.h"
Go to the source code of this file.
#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 |
Definition at line 57 of file sequence.h.
Referenced by AlterSequence(), do_setval(), fill_seq_with_data(), nextval_internal(), seq_desc(), and seq_redo().
typedef FormData_pg_sequence* Form_pg_sequence |
Definition at line 36 of file sequence.h.
typedef struct FormData_pg_sequence FormData_pg_sequence |
typedef struct xl_seq_rec xl_seq_rec |
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 | ) |
Definition at line 525 of file sequence.c.
References nextval_internal(), PG_GETARG_OID, PG_RETURN_INT64, and SeqTableData::relid.
{ Oid relid = PG_GETARG_OID(0); PG_RETURN_INT64(nextval_internal(relid)); }
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); }