PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
sequence.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_sequence.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
#include "commands/tablecmds.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/resowner.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for sequence.c:

Go to the source code of this file.

Data Structures

struct  sequence_magic
 
struct  SeqTableData
 

Macros

#define SEQ_LOG_VALS   32
 
#define SEQ_MAGIC   0x1717
 

Typedefs

typedef struct sequence_magic sequence_magic
 
typedef struct SeqTableData SeqTableData
 
typedef SeqTableDataSeqTable
 

Functions

static void fill_seq_with_data (Relation rel, HeapTuple tuple)
 
static Relation lock_and_open_sequence (SeqTable seq)
 
static void create_seq_hashtable (void)
 
static void init_sequence (Oid relid, SeqTable *p_elm, Relation *p_rel)
 
static Form_pg_sequence_data read_seq_tuple (Relation rel, Buffer *buf, HeapTuple seqdatatuple)
 
static void init_params (ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
 
static void do_setval (Oid relid, int64 next, bool iscalled)
 
static void process_owned_by (Relation seqrel, List *owned_by, bool for_identity)
 
ObjectAddress DefineSequence (ParseState *pstate, CreateSeqStmt *seq)
 
void ResetSequence (Oid seq_relid)
 
ObjectAddress AlterSequence (ParseState *pstate, AlterSeqStmt *stmt)
 
void DeleteSequenceTuple (Oid relid)
 
Datum nextval (PG_FUNCTION_ARGS)
 
Datum nextval_oid (PG_FUNCTION_ARGS)
 
int64 nextval_internal (Oid relid, bool check_permissions)
 
Datum currval_oid (PG_FUNCTION_ARGS)
 
Datum lastval (PG_FUNCTION_ARGS)
 
Datum setval_oid (PG_FUNCTION_ARGS)
 
Datum setval3_oid (PG_FUNCTION_ARGS)
 
Listsequence_options (Oid relid)
 
Datum pg_sequence_parameters (PG_FUNCTION_ARGS)
 
Datum pg_sequence_last_value (PG_FUNCTION_ARGS)
 
void seq_redo (XLogReaderState *record)
 
void ResetSequenceCaches (void)
 
void seq_mask (char *page, BlockNumber blkno)
 

Variables

static HTABseqhashtab = NULL
 
static SeqTableDatalast_used_seq = NULL
 

Macro Definition Documentation

#define SEQ_LOG_VALS   32

Definition at line 54 of file sequence.c.

Referenced by nextval_internal().

#define SEQ_MAGIC   0x1717

Definition at line 59 of file sequence.c.

Referenced by fill_seq_with_data(), read_seq_tuple(), and seq_redo().

Typedef Documentation

Definition at line 85 of file sequence.c.

Function Documentation

ObjectAddress AlterSequence ( ParseState pstate,
AlterSeqStmt stmt 
)

Definition at line 416 of file sequence.c.

References buf, SeqTableData::cached, CatalogTupleUpdate(), elog, ereport, errmsg(), ERROR, fill_seq_with_data(), AlterSeqStmt::for_identity, GETSTRUCT, GetTopTransactionId(), heap_close, heap_copytuple(), heap_open(), HeapTupleIsValid, init_params(), init_sequence(), InvalidMultiXactId, InvalidObjectAddress, InvalidOid, InvalidTransactionId, InvokeObjectPostAlterHook, SeqTableData::last, AlterSeqStmt::missing_ok, NoLock, NOTICE, NULL, ObjectAddressSet, ObjectIdGetDatum, AlterSeqStmt::options, process_owned_by(), RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, read_seq_tuple(), relation_close(), RelationNeedsWAL, RelationRelationId, RelationSetNewRelfilenode(), RangeVar::relname, RowExclusiveLock, SearchSysCacheCopy1, SEQRELID, AlterSeqStmt::sequence, SequenceRelationId, ShareRowExclusiveLock, HeapTupleData::t_self, and UnlockReleaseBuffer().

Referenced by ProcessUtilitySlow().

417 {
418  Oid relid;
419  SeqTable elm;
420  Relation seqrel;
421  Buffer buf;
422  HeapTupleData datatuple;
423  Form_pg_sequence seqform;
424  Form_pg_sequence_data newdataform;
425  bool need_seq_rewrite;
426  List *owned_by;
427  ObjectAddress address;
428  Relation rel;
429  HeapTuple seqtuple;
430  HeapTuple newdatatuple;
431 
432  /* Open and lock sequence, and check for ownership along the way. */
433  relid = RangeVarGetRelidExtended(stmt->sequence,
435  stmt->missing_ok,
436  false,
438  NULL);
439  if (relid == InvalidOid)
440  {
441  ereport(NOTICE,
442  (errmsg("relation \"%s\" does not exist, skipping",
443  stmt->sequence->relname)));
444  return InvalidObjectAddress;
445  }
446 
447  init_sequence(relid, &elm, &seqrel);
448 
450  seqtuple = SearchSysCacheCopy1(SEQRELID,
451  ObjectIdGetDatum(relid));
452  if (!HeapTupleIsValid(seqtuple))
453  elog(ERROR, "cache lookup failed for sequence %u",
454  relid);
455 
456  seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
457 
458  /* lock page's buffer and read tuple into new sequence structure */
459  (void) read_seq_tuple(seqrel, &buf, &datatuple);
460 
461  /* copy the existing sequence data tuple, so it can be modified locally */
462  newdatatuple = heap_copytuple(&datatuple);
463  newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
464 
465  UnlockReleaseBuffer(buf);
466 
467  /* Check and set new values */
468  init_params(pstate, stmt->options, stmt->for_identity, false,
469  seqform, newdataform,
470  &need_seq_rewrite, &owned_by);
471 
472  /* Clear local cache so that we don't think we have cached numbers */
473  /* Note that we do not change the currval() state */
474  elm->cached = elm->last;
475 
476  /* If needed, rewrite the sequence relation itself */
477  if (need_seq_rewrite)
478  {
479  /* check the comment above nextval_internal()'s equivalent call. */
480  if (RelationNeedsWAL(seqrel))
482 
483  /*
484  * Create a new storage file for the sequence, making the state
485  * changes transactional. We want to keep the sequence's relfrozenxid
486  * at 0, since it won't contain any unfrozen XIDs. Same with
487  * relminmxid, since a sequence will never contain multixacts.
488  */
489  RelationSetNewRelfilenode(seqrel, seqrel->rd_rel->relpersistence,
491 
492  /*
493  * Insert the modified tuple into the new storage file.
494  */
495  fill_seq_with_data(seqrel, newdatatuple);
496  }
497 
498  /* process OWNED BY if given */
499  if (owned_by)
500  process_owned_by(seqrel, owned_by, stmt->for_identity);
501 
502  /* update the pg_sequence tuple (we could skip this in some cases...) */
503  CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple);
504 
506 
507  ObjectAddressSet(address, RelationRelationId, relid);
508 
510  relation_close(seqrel, NoLock);
511 
512  return address;
513 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
int64 cached
Definition: sequence.c:79
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3422
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define SequenceRelationId
Definition: pg_sequence.h:6
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
#define heap_close(r, l)
Definition: heapam.h:97
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
List * options
Definition: parsenodes.h:2473
char * relname
Definition: primnodes.h:68
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:12998
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1639
int64 last
Definition: sequence.c:78
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1168
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidMultiXactId
Definition: multixact.h:23
#define InvalidOid
Definition: postgres_ext.h:36
RangeVar * sequence
Definition: parsenodes.h:2472
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define ShareRowExclusiveLock
Definition: lockdefs.h:42
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define RelationNeedsWAL(relation)
Definition: rel.h:505
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
Definition: sequence.c:1234
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool for_identity
Definition: parsenodes.h:2474
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
int Buffer
Definition: buf.h:23
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:337
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
static void create_seq_hashtable ( void  )
static

Definition at line 1084 of file sequence.c.

References HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, and HASHCTL::keysize.

Referenced by init_sequence().

1085 {
1086  HASHCTL ctl;
1087 
1088  memset(&ctl, 0, sizeof(ctl));
1089  ctl.keysize = sizeof(Oid);
1090  ctl.entrysize = sizeof(SeqTableData);
1091 
1092  seqhashtab = hash_create("Sequence values", 16, &ctl,
1093  HASH_ELEM | HASH_BLOBS);
1094 }
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
struct SeqTableData SeqTableData
unsigned int Oid
Definition: postgres_ext.h:31
static HTAB * seqhashtab
Definition: sequence.c:87
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
Datum currval_oid ( PG_FUNCTION_ARGS  )

Definition at line 820 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, SeqTableData::relid, and result.

821 {
822  Oid relid = PG_GETARG_OID(0);
823  int64 result;
824  SeqTable elm;
825  Relation seqrel;
826 
827  /* open and lock sequence */
828  init_sequence(relid, &elm, &seqrel);
829 
830  if (pg_class_aclcheck(elm->relid, GetUserId(),
832  ereport(ERROR,
833  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
834  errmsg("permission denied for sequence %s",
835  RelationGetRelationName(seqrel))));
836 
837  if (!elm->last_valid)
838  ereport(ERROR,
839  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
840  errmsg("currval of sequence \"%s\" is not yet defined in this session",
841  RelationGetRelationName(seqrel))));
842 
843  result = elm->last;
844 
845  relation_close(seqrel, NoLock);
846 
847  PG_RETURN_INT64(result);
848 }
Oid GetUserId(void)
Definition: miscinit.c:284
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
return result
Definition: formatting.c:1633
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
#define RelationGetRelationName(relation)
Definition: rel.h:436
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_SELECT
Definition: parsenodes.h:73
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
int errmsg(const char *fmt,...)
Definition: elog.c:797
ObjectAddress DefineSequence ( ParseState pstate,
CreateSeqStmt seq 
)

Definition at line 116 of file sequence.c.

References AccessExclusiveLock, Anum_pg_sequence_seqcache, Anum_pg_sequence_seqcycle, Anum_pg_sequence_seqincrement, Anum_pg_sequence_seqmax, Anum_pg_sequence_seqmin, Anum_pg_sequence_seqrelid, Anum_pg_sequence_seqstart, Anum_pg_sequence_seqtypid, Assert, BoolGetDatum, BOOLOID, CatalogTupleInsert(), ColumnDef::collClause, ColumnDef::collOid, ColumnDef::colname, ColumnDef::constraints, CreateStmt::constraints, ColumnDef::cooked_default, DefineRelation(), ereport, errcode(), errmsg(), ERROR, fill_seq_with_data(), CreateSeqStmt::for_identity, FormData_pg_sequence, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), i, CreateStmt::if_not_exists, CreateSeqStmt::if_not_exists, ColumnDef::inhcount, CreateStmt::inhRelations, init_params(), Int64GetDatum(), Int64GetDatumFast, INT8OID, InvalidObjectAddress, InvalidOid, ColumnDef::is_from_parent, ColumnDef::is_from_type, ColumnDef::is_local, ColumnDef::is_not_null, lappend(), FormData_pg_sequence_data::last_value, ColumnDef::location, makeNode, makeTypeNameFromOid(), Natts_pg_sequence, NIL, NoLock, NOTICE, NULL, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, CreateSeqStmt::options, CreateSeqStmt::ownerId, process_owned_by(), RangeVarGetAndCheckCreationNamespace(), ColumnDef::raw_default, CreateStmt::relation, RelationGetDescr, RELKIND_SEQUENCE, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_UNLOGGED, RowExclusiveLock, SEQ_COL_CALLED, SEQ_COL_FIRSTCOL, SEQ_COL_LASTCOL, SEQ_COL_LASTVAL, SEQ_COL_LOG, CreateSeqStmt::sequence, SequenceRelationId, ColumnDef::storage, CreateStmt::tableElts, CreateStmt::tablespacename, ColumnDef::typeName, and value.

Referenced by ProcessUtilitySlow().

117 {
118  FormData_pg_sequence seqform;
119  FormData_pg_sequence_data seqdataform;
120  bool need_seq_rewrite;
121  List *owned_by;
122  CreateStmt *stmt = makeNode(CreateStmt);
123  Oid seqoid;
124  ObjectAddress address;
125  Relation rel;
126  HeapTuple tuple;
127  TupleDesc tupDesc;
129  bool null[SEQ_COL_LASTCOL];
130  Datum pgs_values[Natts_pg_sequence];
131  bool pgs_nulls[Natts_pg_sequence];
132  int i;
133 
134  /* Unlogged sequences are not implemented -- not clear if useful. */
136  ereport(ERROR,
137  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
138  errmsg("unlogged sequences are not supported")));
139 
140  /*
141  * If if_not_exists was given and a relation with the same name already
142  * exists, bail out. (Note: we needn't check this when not if_not_exists,
143  * because DefineRelation will complain anyway.)
144  */
145  if (seq->if_not_exists)
146  {
148  if (OidIsValid(seqoid))
149  {
150  ereport(NOTICE,
151  (errcode(ERRCODE_DUPLICATE_TABLE),
152  errmsg("relation \"%s\" already exists, skipping",
153  seq->sequence->relname)));
154  return InvalidObjectAddress;
155  }
156  }
157 
158  /* Check and set all option values */
159  init_params(pstate, seq->options, seq->for_identity, true,
160  &seqform, &seqdataform,
161  &need_seq_rewrite, &owned_by);
162 
163  /*
164  * Create relation (and fill value[] and null[] for the tuple)
165  */
166  stmt->tableElts = NIL;
167  for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
168  {
169  ColumnDef *coldef = makeNode(ColumnDef);
170 
171  coldef->inhcount = 0;
172  coldef->is_local = true;
173  coldef->is_not_null = true;
174  coldef->is_from_type = false;
175  coldef->is_from_parent = false;
176  coldef->storage = 0;
177  coldef->raw_default = NULL;
178  coldef->cooked_default = NULL;
179  coldef->collClause = NULL;
180  coldef->collOid = InvalidOid;
181  coldef->constraints = NIL;
182  coldef->location = -1;
183 
184  null[i - 1] = false;
185 
186  switch (i)
187  {
188  case SEQ_COL_LASTVAL:
189  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
190  coldef->colname = "last_value";
191  value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
192  break;
193  case SEQ_COL_LOG:
194  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
195  coldef->colname = "log_cnt";
196  value[i - 1] = Int64GetDatum((int64) 0);
197  break;
198  case SEQ_COL_CALLED:
199  coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
200  coldef->colname = "is_called";
201  value[i - 1] = BoolGetDatum(false);
202  break;
203  }
204  stmt->tableElts = lappend(stmt->tableElts, coldef);
205  }
206 
207  stmt->relation = seq->sequence;
208  stmt->inhRelations = NIL;
209  stmt->constraints = NIL;
210  stmt->options = NIL;
211  stmt->oncommit = ONCOMMIT_NOOP;
212  stmt->tablespacename = NULL;
213  stmt->if_not_exists = seq->if_not_exists;
214 
215  address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
216  seqoid = address.objectId;
217  Assert(seqoid != InvalidOid);
218 
219  rel = heap_open(seqoid, AccessExclusiveLock);
220  tupDesc = RelationGetDescr(rel);
221 
222  /* now initialize the sequence's data */
223  tuple = heap_form_tuple(tupDesc, value, null);
224  fill_seq_with_data(rel, tuple);
225 
226  /* process OWNED BY if given */
227  if (owned_by)
228  process_owned_by(rel, owned_by, seq->for_identity);
229 
230  heap_close(rel, NoLock);
231 
232  /* fill in pg_sequence */
234  tupDesc = RelationGetDescr(rel);
235 
236  memset(pgs_nulls, 0, sizeof(pgs_nulls));
237 
238  pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
239  pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
240  pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
241  pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
242  pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
243  pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
244  pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
245  pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
246 
247  tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
248  CatalogTupleInsert(rel, tuple);
249 
250  heap_freetuple(tuple);
252 
253  return address;
254 }
RangeVar * relation
Definition: parsenodes.h:1995
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: parsenodes.h:2004
List * inhRelations
Definition: parsenodes.h:1997
char storage
Definition: parsenodes.h:646
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
bool is_local
Definition: parsenodes.h:642
#define RelationGetDescr(relation)
Definition: rel.h:428
List * constraints
Definition: parsenodes.h:652
bool if_not_exists
Definition: parsenodes.h:2466
bool is_from_parent
Definition: parsenodes.h:645
#define Anum_pg_sequence_seqcache
Definition: pg_sequence.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SequenceRelationId
Definition: pg_sequence.h:6
#define SEQ_COL_FIRSTCOL
Definition: sequence.h:42
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
bool is_not_null
Definition: parsenodes.h:643
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define Anum_pg_sequence_seqtypid
Definition: pg_sequence.h:24
List * constraints
Definition: parsenodes.h:2002
bool if_not_exists
Definition: parsenodes.h:2006
Node * cooked_default
Definition: parsenodes.h:648
char * relname
Definition: primnodes.h:68
#define SEQ_COL_LASTVAL
Definition: sequence.h:38
FormData_pg_sequence
Definition: pg_sequence.h:18
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Natts_pg_sequence
Definition: pg_sequence.h:22
static struct @121 value
#define NoLock
Definition: lockdefs.h:34
Oid collOid
Definition: parsenodes.h:651
#define RowExclusiveLock
Definition: lockdefs.h:38
List * options
Definition: parsenodes.h:2003
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1639
int location
Definition: parsenodes.h:654
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:498
#define ereport(elevel, rest)
Definition: elog.h:122
#define SEQ_COL_LOG
Definition: sequence.h:39
Node * raw_default
Definition: parsenodes.h:647
List * lappend(List *list, void *datum)
Definition: list.c:128
char * tablespacename
Definition: parsenodes.h:2005
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
uintptr_t Datum
Definition: postgres.h:372
#define Anum_pg_sequence_seqmin
Definition: pg_sequence.h:28
#define Anum_pg_sequence_seqcycle
Definition: pg_sequence.h:30
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Int64GetDatumFast(X)
Definition: postgres.h:781
#define BoolGetDatum(X)
Definition: postgres.h:408
TypeName * makeTypeNameFromOid(Oid typeOid, int32 typmod)
Definition: makefuncs.c:469
#define InvalidOid
Definition: postgres_ext.h:36
RangeVar * sequence
Definition: parsenodes.h:2462
bool is_from_type
Definition: parsenodes.h:644
#define NOTICE
Definition: elog.h:37
#define INT8OID
Definition: pg_type.h:304
List * tableElts
Definition: parsenodes.h:1996
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
TypeName * typeName
Definition: parsenodes.h:640
CollateClause * collClause
Definition: parsenodes.h:650
#define Anum_pg_sequence_seqstart
Definition: pg_sequence.h:25
#define BOOLOID
Definition: pg_type.h:288
char relpersistence
Definition: primnodes.h:71
#define SEQ_COL_LASTCOL
Definition: sequence.h:43
#define AccessExclusiveLock
Definition: lockdefs.h:45
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
Definition: sequence.c:1234
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SEQ_COL_CALLED
Definition: sequence.h:40
#define Anum_pg_sequence_seqrelid
Definition: pg_sequence.h:23
int i
int inhcount
Definition: parsenodes.h:641
char * colname
Definition: parsenodes.h:639
#define Anum_pg_sequence_seqincrement
Definition: pg_sequence.h:26
#define Anum_pg_sequence_seqmax
Definition: pg_sequence.h:27
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:337
List * options
Definition: parsenodes.h:2463
void DeleteSequenceTuple ( Oid  relid)

Definition at line 516 of file sequence.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1, SEQRELID, SequenceRelationId, and HeapTupleData::t_self.

Referenced by doDeletion().

517 {
518  Relation rel;
519  HeapTuple tuple;
520 
522 
523  tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
524  if (!HeapTupleIsValid(tuple))
525  elog(ERROR, "cache lookup failed for sequence %u", relid);
526 
527  CatalogTupleDelete(rel, &tuple->t_self);
528 
529  ReleaseSysCache(tuple);
531 }
#define SequenceRelationId
Definition: pg_sequence.h:6
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
static void do_setval ( Oid  relid,
int64  next,
bool  iscalled 
)
static

Definition at line 899 of file sequence.c.

References ACL_UPDATE, ACLCHECK_OK, buf, BufferGetPage, SeqTableData::cached, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetTopTransactionId(), GetUserId(), HeapTupleIsValid, init_sequence(), INT64_FORMAT, FormData_pg_sequence_data::is_called, SeqTableData::last, SeqTableData::last_valid, FormData_pg_sequence_data::last_value, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, xl_seq_rec::node, NoLock, ObjectIdGetDatum, PageSetLSN, pg_class_aclcheck(), PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RelationData::rd_islocaltemp, RelationData::rd_node, read_seq_tuple(), REGBUF_WILL_INIT, relation_close(), RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, SearchSysCache1, SEQRELID, snprintf(), START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by setval3_oid(), and setval_oid().

900 {
901  SeqTable elm;
902  Relation seqrel;
903  Buffer buf;
904  HeapTupleData seqdatatuple;
906  HeapTuple pgstuple;
907  Form_pg_sequence pgsform;
908  int64 maxv,
909  minv;
910 
911  /* open and lock sequence */
912  init_sequence(relid, &elm, &seqrel);
913 
915  ereport(ERROR,
916  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
917  errmsg("permission denied for sequence %s",
918  RelationGetRelationName(seqrel))));
919 
920  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
921  if (!HeapTupleIsValid(pgstuple))
922  elog(ERROR, "cache lookup failed for sequence %u", relid);
923  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
924  maxv = pgsform->seqmax;
925  minv = pgsform->seqmin;
926  ReleaseSysCache(pgstuple);
927 
928  /* read-only transactions may only modify temp sequences */
929  if (!seqrel->rd_islocaltemp)
930  PreventCommandIfReadOnly("setval()");
931 
932  /*
933  * Forbid this during parallel operation because, to make it work, the
934  * cooperating backends would need to share the backend-local cached
935  * sequence information. Currently, we don't support that.
936  */
937  PreventCommandIfParallelMode("setval()");
938 
939  /* lock page' buffer and read tuple */
940  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
941 
942  if ((next < minv) || (next > maxv))
943  {
944  char bufv[100],
945  bufm[100],
946  bufx[100];
947 
948  snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
949  snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
950  snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
951  ereport(ERROR,
952  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
953  errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
954  bufv, RelationGetRelationName(seqrel),
955  bufm, bufx)));
956  }
957 
958  /* Set the currval() state only if iscalled = true */
959  if (iscalled)
960  {
961  elm->last = next; /* last returned number */
962  elm->last_valid = true;
963  }
964 
965  /* In any case, forget any future cached numbers */
966  elm->cached = elm->last;
967 
968  /* check the comment above nextval_internal()'s equivalent call. */
969  if (RelationNeedsWAL(seqrel))
971 
972  /* ready to change the on-disk (or really, in-buffer) tuple */
974 
975  seq->last_value = next; /* last fetched number */
976  seq->is_called = iscalled;
977  seq->log_cnt = 0;
978 
979  MarkBufferDirty(buf);
980 
981  /* XLOG stuff */
982  if (RelationNeedsWAL(seqrel))
983  {
984  xl_seq_rec xlrec;
985  XLogRecPtr recptr;
986  Page page = BufferGetPage(buf);
987 
988  XLogBeginInsert();
990 
991  xlrec.node = seqrel->rd_node;
992  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
993  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
994 
995  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
996 
997  PageSetLSN(page, recptr);
998  }
999 
1000  END_CRIT_SECTION();
1001 
1002  UnlockReleaseBuffer(buf);
1003 
1004  relation_close(seqrel, NoLock);
1005 }
int64 cached
Definition: sequence.c:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static int32 next
Definition: blutils.c:210
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:254
Oid GetUserId(void)
Definition: miscinit.c:284
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
bool last_valid
Definition: sequence.c:77
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
bool rd_islocaltemp
Definition: rel.h:90
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
RelFileNode node
Definition: sequence.h:50
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define RelationGetRelationName(relation)
Definition: rel.h:436
int64 last
Definition: sequence.c:78
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1168
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define ACL_UPDATE
Definition: parsenodes.h:74
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define RelationNeedsWAL(relation)
Definition: rel.h:505
#define INT64_FORMAT
Definition: c.h:315
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:236
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
static void fill_seq_with_data ( Relation  rel,
HeapTuple  tuple 
)
static

Definition at line 337 of file sequence.c.

References Assert, buf, BUFFER_LOCK_EXCLUSIVE, BufferGetBlockNumber(), BufferGetPage, BufferGetPageSize, elog, END_CRIT_SECTION, ERROR, FirstCommandId, FirstOffsetNumber, FrozenTransactionId, GetTopTransactionId(), HEAP_XMAX_INVALID, HeapTupleHeaderSetCmin, HeapTupleHeaderSetXmax, HeapTupleHeaderSetXmin, HeapTupleHeaderSetXminFrozen, InvalidOffsetNumber, InvalidTransactionId, ItemPointerSet, LockBuffer(), sequence_magic::magic, MarkBufferDirty(), xl_seq_rec::node, P_NEW, PageAddItem, PageGetSpecialPointer, PageInit(), PageSetLSN, RelationData::rd_node, ReadBuffer(), REGBUF_WILL_INIT, RelationNeedsWAL, SEQ_MAGIC, START_CRIT_SECTION, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by AlterSequence(), DefineSequence(), and ResetSequence().

338 {
339  Buffer buf;
340  Page page;
341  sequence_magic *sm;
342  OffsetNumber offnum;
343 
344  /* Initialize first page of relation with special magic number */
345 
346  buf = ReadBuffer(rel, P_NEW);
347  Assert(BufferGetBlockNumber(buf) == 0);
348 
349  page = BufferGetPage(buf);
350 
351  PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
352  sm = (sequence_magic *) PageGetSpecialPointer(page);
353  sm->magic = SEQ_MAGIC;
354 
355  /* Now insert sequence tuple */
356 
358 
359  /*
360  * Since VACUUM does not process sequences, we have to force the tuple to
361  * have xmin = FrozenTransactionId now. Otherwise it would become
362  * invisible to SELECTs after 2G transactions. It is okay to do this
363  * because if the current transaction aborts, no other xact will ever
364  * examine the sequence tuple anyway.
365  */
372 
373  /* check the comment above nextval_internal()'s equivalent call. */
374  if (RelationNeedsWAL(rel))
376 
378 
379  MarkBufferDirty(buf);
380 
381  offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
382  InvalidOffsetNumber, false, false);
383  if (offnum != FirstOffsetNumber)
384  elog(ERROR, "failed to add sequence tuple to page");
385 
386  /* XLOG stuff */
387  if (RelationNeedsWAL(rel))
388  {
389  xl_seq_rec xlrec;
390  XLogRecPtr recptr;
391 
392  XLogBeginInsert();
394 
395  xlrec.node = rel->rd_node;
396 
397  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
398  XLogRegisterData((char *) tuple->t_data, tuple->t_len);
399 
400  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
401 
402  PageSetLSN(page, recptr);
403  }
404 
406 
407  UnlockReleaseBuffer(buf);
408 }
#define SEQ_MAGIC
Definition: sequence.c:59
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
Pointer Item
Definition: item.h:17
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
#define P_NEW
Definition: bufmgr.h:82
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
RelFileNode node
Definition: sequence.h:50
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define FirstCommandId
Definition: c.h:413
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_ctid
Definition: htup_details.h:150
uint32 t_len
Definition: htup.h:64
static char * buf
Definition: pg_test_fsync.c:66
#define FirstOffsetNumber
Definition: off.h:27
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
#define InvalidTransactionId
Definition: transam.h:31
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define InvalidOffsetNumber
Definition: off.h:26
RelFileNode rd_node
Definition: rel.h:85
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:676
#define FrozenTransactionId
Definition: transam.h:33
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint32 magic
Definition: sequence.c:63
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define RelationNeedsWAL(relation)
Definition: rel.h:505
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define HeapTupleHeaderSetXminFrozen(tup)
Definition: htup_details.h:346
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:391
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:105
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:313
static void init_params ( ParseState pstate,
List options,
bool  for_identity,
bool  isInit,
Form_pg_sequence  seqform,
Form_pg_sequence_data  seqdataform,
bool need_seq_rewrite,
List **  owned_by 
)
static

Definition at line 1234 of file sequence.c.

References DefElem::arg, Assert, BoolIsValid, buf, defGetInt64(), defGetQualifiedName(), defGetTypeName(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), INT2OID, INT4OID, INT64_FORMAT, INT8OID, intVal, FormData_pg_sequence_data::is_called, FormData_pg_sequence_data::last_value, lfirst, DefElem::location, FormData_pg_sequence_data::log_cnt, NIL, NULL, parser_errposition(), PG_INT16_MAX, PG_INT16_MIN, PG_INT32_MAX, PG_INT32_MIN, PG_INT64_MAX, PG_INT64_MIN, snprintf(), and typenameTypeId().

Referenced by AlterSequence(), and DefineSequence().

1240 {
1241  DefElem *as_type = NULL;
1242  DefElem *start_value = NULL;
1243  DefElem *restart_value = NULL;
1244  DefElem *increment_by = NULL;
1245  DefElem *max_value = NULL;
1246  DefElem *min_value = NULL;
1247  DefElem *cache_value = NULL;
1248  DefElem *is_cycled = NULL;
1249  ListCell *option;
1250  bool reset_max_value = false;
1251  bool reset_min_value = false;
1252 
1253  *need_seq_rewrite = false;
1254  *owned_by = NIL;
1255 
1256  foreach(option, options)
1257  {
1258  DefElem *defel = (DefElem *) lfirst(option);
1259 
1260  if (strcmp(defel->defname, "as") == 0)
1261  {
1262  if (as_type)
1263  ereport(ERROR,
1264  (errcode(ERRCODE_SYNTAX_ERROR),
1265  errmsg("conflicting or redundant options"),
1266  parser_errposition(pstate, defel->location)));
1267  as_type = defel;
1268  *need_seq_rewrite = true;
1269  }
1270  else if (strcmp(defel->defname, "increment") == 0)
1271  {
1272  if (increment_by)
1273  ereport(ERROR,
1274  (errcode(ERRCODE_SYNTAX_ERROR),
1275  errmsg("conflicting or redundant options"),
1276  parser_errposition(pstate, defel->location)));
1277  increment_by = defel;
1278  *need_seq_rewrite = true;
1279  }
1280  else if (strcmp(defel->defname, "start") == 0)
1281  {
1282  if (start_value)
1283  ereport(ERROR,
1284  (errcode(ERRCODE_SYNTAX_ERROR),
1285  errmsg("conflicting or redundant options"),
1286  parser_errposition(pstate, defel->location)));
1287  start_value = defel;
1288  *need_seq_rewrite = true;
1289  }
1290  else if (strcmp(defel->defname, "restart") == 0)
1291  {
1292  if (restart_value)
1293  ereport(ERROR,
1294  (errcode(ERRCODE_SYNTAX_ERROR),
1295  errmsg("conflicting or redundant options"),
1296  parser_errposition(pstate, defel->location)));
1297  restart_value = defel;
1298  *need_seq_rewrite = true;
1299  }
1300  else if (strcmp(defel->defname, "maxvalue") == 0)
1301  {
1302  if (max_value)
1303  ereport(ERROR,
1304  (errcode(ERRCODE_SYNTAX_ERROR),
1305  errmsg("conflicting or redundant options"),
1306  parser_errposition(pstate, defel->location)));
1307  max_value = defel;
1308  *need_seq_rewrite = true;
1309  }
1310  else if (strcmp(defel->defname, "minvalue") == 0)
1311  {
1312  if (min_value)
1313  ereport(ERROR,
1314  (errcode(ERRCODE_SYNTAX_ERROR),
1315  errmsg("conflicting or redundant options"),
1316  parser_errposition(pstate, defel->location)));
1317  min_value = defel;
1318  *need_seq_rewrite = true;
1319  }
1320  else if (strcmp(defel->defname, "cache") == 0)
1321  {
1322  if (cache_value)
1323  ereport(ERROR,
1324  (errcode(ERRCODE_SYNTAX_ERROR),
1325  errmsg("conflicting or redundant options"),
1326  parser_errposition(pstate, defel->location)));
1327  cache_value = defel;
1328  *need_seq_rewrite = true;
1329  }
1330  else if (strcmp(defel->defname, "cycle") == 0)
1331  {
1332  if (is_cycled)
1333  ereport(ERROR,
1334  (errcode(ERRCODE_SYNTAX_ERROR),
1335  errmsg("conflicting or redundant options"),
1336  parser_errposition(pstate, defel->location)));
1337  is_cycled = defel;
1338  *need_seq_rewrite = true;
1339  }
1340  else if (strcmp(defel->defname, "owned_by") == 0)
1341  {
1342  if (*owned_by)
1343  ereport(ERROR,
1344  (errcode(ERRCODE_SYNTAX_ERROR),
1345  errmsg("conflicting or redundant options"),
1346  parser_errposition(pstate, defel->location)));
1347  *owned_by = defGetQualifiedName(defel);
1348  }
1349  else if (strcmp(defel->defname, "sequence_name") == 0)
1350  {
1351  /*
1352  * The parser allows this, but it is only for identity columns, in
1353  * which case it is filtered out in parse_utilcmd.c. We only get
1354  * here if someone puts it into a CREATE SEQUENCE.
1355  */
1356  ereport(ERROR,
1357  (errcode(ERRCODE_SYNTAX_ERROR),
1358  errmsg("invalid sequence option SEQUENCE NAME"),
1359  parser_errposition(pstate, defel->location)));
1360  }
1361  else
1362  elog(ERROR, "option \"%s\" not recognized",
1363  defel->defname);
1364  }
1365 
1366  /*
1367  * We must reset log_cnt when isInit or when changing any parameters that
1368  * would affect future nextval allocations.
1369  */
1370  if (isInit)
1371  seqdataform->log_cnt = 0;
1372 
1373  /* AS type */
1374  if (as_type != NULL)
1375  {
1376  Oid newtypid = typenameTypeId(pstate, defGetTypeName(as_type));
1377 
1378  if (newtypid != INT2OID &&
1379  newtypid != INT4OID &&
1380  newtypid != INT8OID)
1381  ereport(ERROR,
1382  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1383  for_identity
1384  ? errmsg("identity column type must be smallint, integer, or bigint")
1385  : errmsg("sequence type must be smallint, integer, or bigint")));
1386 
1387  if (!isInit)
1388  {
1389  /*
1390  * When changing type and the old sequence min/max values were the
1391  * min/max of the old type, adjust sequence min/max values to
1392  * min/max of new type. (Otherwise, the user chose explicit
1393  * min/max values, which we'll leave alone.)
1394  */
1395  if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX) ||
1396  (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX) ||
1397  (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX))
1398  reset_max_value = true;
1399  if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN) ||
1400  (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN) ||
1401  (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN))
1402  reset_min_value = true;
1403  }
1404 
1405  seqform->seqtypid = newtypid;
1406  }
1407  else if (isInit)
1408  {
1409  seqform->seqtypid = INT8OID;
1410  }
1411 
1412  /* INCREMENT BY */
1413  if (increment_by != NULL)
1414  {
1415  seqform->seqincrement = defGetInt64(increment_by);
1416  if (seqform->seqincrement == 0)
1417  ereport(ERROR,
1418  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1419  errmsg("INCREMENT must not be zero")));
1420  seqdataform->log_cnt = 0;
1421  }
1422  else if (isInit)
1423  {
1424  seqform->seqincrement = 1;
1425  }
1426 
1427  /* CYCLE */
1428  if (is_cycled != NULL)
1429  {
1430  seqform->seqcycle = intVal(is_cycled->arg);
1431  Assert(BoolIsValid(seqform->seqcycle));
1432  seqdataform->log_cnt = 0;
1433  }
1434  else if (isInit)
1435  {
1436  seqform->seqcycle = false;
1437  }
1438 
1439  /* MAXVALUE (null arg means NO MAXVALUE) */
1440  if (max_value != NULL && max_value->arg)
1441  {
1442  seqform->seqmax = defGetInt64(max_value);
1443  seqdataform->log_cnt = 0;
1444  }
1445  else if (isInit || max_value != NULL || reset_max_value)
1446  {
1447  if (seqform->seqincrement > 0 || reset_max_value)
1448  {
1449  /* ascending seq */
1450  if (seqform->seqtypid == INT2OID)
1451  seqform->seqmax = PG_INT16_MAX;
1452  else if (seqform->seqtypid == INT4OID)
1453  seqform->seqmax = PG_INT32_MAX;
1454  else
1455  seqform->seqmax = PG_INT64_MAX;
1456  }
1457  else
1458  seqform->seqmax = -1; /* descending seq */
1459  seqdataform->log_cnt = 0;
1460  }
1461 
1462  if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
1463  || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX))
1464  || (seqform->seqtypid == INT8OID && (seqform->seqmax < PG_INT64_MIN || seqform->seqmax > PG_INT64_MAX)))
1465  {
1466  char bufx[100];
1467 
1468  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1469 
1470  ereport(ERROR,
1471  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1472  errmsg("MAXVALUE (%s) is out of range for sequence data type %s",
1473  bufx, format_type_be(seqform->seqtypid))));
1474  }
1475 
1476  /* MINVALUE (null arg means NO MINVALUE) */
1477  if (min_value != NULL && min_value->arg)
1478  {
1479  seqform->seqmin = defGetInt64(min_value);
1480  seqdataform->log_cnt = 0;
1481  }
1482  else if (isInit || min_value != NULL || reset_min_value)
1483  {
1484  if (seqform->seqincrement < 0 || reset_min_value)
1485  {
1486  /* descending seq */
1487  if (seqform->seqtypid == INT2OID)
1488  seqform->seqmin = PG_INT16_MIN;
1489  else if (seqform->seqtypid == INT4OID)
1490  seqform->seqmin = PG_INT32_MIN;
1491  else
1492  seqform->seqmin = PG_INT64_MIN;
1493  }
1494  else
1495  seqform->seqmin = 1; /* ascending seq */
1496  seqdataform->log_cnt = 0;
1497  }
1498 
1499  if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
1500  || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX))
1501  || (seqform->seqtypid == INT8OID && (seqform->seqmin < PG_INT64_MIN || seqform->seqmin > PG_INT64_MAX)))
1502  {
1503  char bufm[100];
1504 
1505  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1506 
1507  ereport(ERROR,
1508  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1509  errmsg("MINVALUE (%s) is out of range for sequence data type %s",
1510  bufm, format_type_be(seqform->seqtypid))));
1511  }
1512 
1513  /* crosscheck min/max */
1514  if (seqform->seqmin >= seqform->seqmax)
1515  {
1516  char bufm[100],
1517  bufx[100];
1518 
1519  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1520  snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
1521  ereport(ERROR,
1522  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1523  errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
1524  bufm, bufx)));
1525  }
1526 
1527  /* START WITH */
1528  if (start_value != NULL)
1529  {
1530  seqform->seqstart = defGetInt64(start_value);
1531  }
1532  else if (isInit)
1533  {
1534  if (seqform->seqincrement > 0)
1535  seqform->seqstart = seqform->seqmin; /* ascending seq */
1536  else
1537  seqform->seqstart = seqform->seqmax; /* descending seq */
1538  }
1539 
1540  /* crosscheck START */
1541  if (seqform->seqstart < seqform->seqmin)
1542  {
1543  char bufs[100],
1544  bufm[100];
1545 
1546  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1547  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1548  ereport(ERROR,
1549  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1550  errmsg("START value (%s) cannot be less than MINVALUE (%s)",
1551  bufs, bufm)));
1552  }
1553  if (seqform->seqstart > seqform->seqmax)
1554  {
1555  char bufs[100],
1556  bufm[100];
1557 
1558  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
1559  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1560  ereport(ERROR,
1561  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1562  errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
1563  bufs, bufm)));
1564  }
1565 
1566  /* RESTART [WITH] */
1567  if (restart_value != NULL)
1568  {
1569  if (restart_value->arg != NULL)
1570  seqdataform->last_value = defGetInt64(restart_value);
1571  else
1572  seqdataform->last_value = seqform->seqstart;
1573  seqdataform->is_called = false;
1574  seqdataform->log_cnt = 0;
1575  }
1576  else if (isInit)
1577  {
1578  seqdataform->last_value = seqform->seqstart;
1579  seqdataform->is_called = false;
1580  }
1581 
1582  /* crosscheck RESTART (or current value, if changing MIN/MAX) */
1583  if (seqdataform->last_value < seqform->seqmin)
1584  {
1585  char bufs[100],
1586  bufm[100];
1587 
1588  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1589  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
1590  ereport(ERROR,
1591  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1592  errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
1593  bufs, bufm)));
1594  }
1595  if (seqdataform->last_value > seqform->seqmax)
1596  {
1597  char bufs[100],
1598  bufm[100];
1599 
1600  snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
1601  snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
1602  ereport(ERROR,
1603  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1604  errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
1605  bufs, bufm)));
1606  }
1607 
1608  /* CACHE */
1609  if (cache_value != NULL)
1610  {
1611  seqform->seqcache = defGetInt64(cache_value);
1612  if (seqform->seqcache <= 0)
1613  {
1614  char buf[100];
1615 
1616  snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
1617  ereport(ERROR,
1618  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1619  errmsg("CACHE (%s) must be greater than zero",
1620  buf)));
1621  }
1622  seqdataform->log_cnt = 0;
1623  }
1624  else if (isInit)
1625  {
1626  seqform->seqcache = 1;
1627  }
1628 }
#define NIL
Definition: pg_list.h:69
#define PG_INT64_MAX
Definition: c.h:343
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
int64 defGetInt64(DefElem *def)
Definition: define.c:190
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
unsigned int Oid
Definition: postgres_ext.h:31
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
#define ERROR
Definition: elog.h:43
#define INT2OID
Definition: pg_type.h:308
static char * buf
Definition: pg_test_fsync.c:66
#define PG_INT64_MIN
Definition: c.h:342
int location
Definition: parsenodes.h:722
#define PG_INT16_MIN
Definition: c.h:336
#define PG_INT32_MIN
Definition: c.h:339
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
#define INT8OID
Definition: pg_type.h:304
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define PG_INT16_MAX
Definition: c.h:337
#define INT64_FORMAT
Definition: c.h:315
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_INT32_MAX
Definition: c.h:340
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
#define BoolIsValid(boolean)
Definition: c.h:520
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
static void init_sequence ( Oid  relid,
SeqTable p_elm,
Relation p_rel 
)
static

Definition at line 1101 of file sequence.c.

References SeqTableData::cached, create_seq_hashtable(), ereport, errcode(), errmsg(), ERROR, SeqTableData::filenode, HASH_ENTER, hash_search(), InvalidLocalTransactionId, InvalidOid, SeqTableData::last, SeqTableData::last_valid, lock_and_open_sequence(), SeqTableData::lxid, NULL, RelationData::rd_rel, RelationGetRelationName, and RELKIND_SEQUENCE.

Referenced by AlterSequence(), currval_oid(), do_setval(), nextval_internal(), pg_sequence_last_value(), and ResetSequence().

1102 {
1103  SeqTable elm;
1104  Relation seqrel;
1105  bool found;
1106 
1107  /* Find or create a hash table entry for this sequence */
1108  if (seqhashtab == NULL)
1110 
1111  elm = (SeqTable) hash_search(seqhashtab, &relid, HASH_ENTER, &found);
1112 
1113  /*
1114  * Initialize the new hash table entry if it did not exist already.
1115  *
1116  * NOTE: seqtable entries are stored for the life of a backend (unless
1117  * explicitly discarded with DISCARD). If the sequence itself is deleted
1118  * then the entry becomes wasted memory, but it's small enough that this
1119  * should not matter.
1120  */
1121  if (!found)
1122  {
1123  /* relid already filled in */
1124  elm->filenode = InvalidOid;
1126  elm->last_valid = false;
1127  elm->last = elm->cached = 0;
1128  }
1129 
1130  /*
1131  * Open the sequence relation.
1132  */
1133  seqrel = lock_and_open_sequence(elm);
1134 
1135  if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
1136  ereport(ERROR,
1137  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1138  errmsg("\"%s\" is not a sequence",
1139  RelationGetRelationName(seqrel))));
1140 
1141  /*
1142  * If the sequence has been transactionally replaced since we last saw it,
1143  * discard any cached-but-unissued values. We do not touch the currval()
1144  * state, however.
1145  */
1146  if (seqrel->rd_rel->relfilenode != elm->filenode)
1147  {
1148  elm->filenode = seqrel->rd_rel->relfilenode;
1149  elm->cached = elm->last;
1150  }
1151 
1152  /* Return results */
1153  *p_elm = elm;
1154  *p_rel = seqrel;
1155 }
int64 cached
Definition: sequence.c:79
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
Form_pg_class rd_rel
Definition: rel.h:114
static HTAB * seqhashtab
Definition: sequence.c:87
#define ERROR
Definition: elog.h:43
static void create_seq_hashtable(void)
Definition: sequence.c:1084
#define RelationGetRelationName(relation)
Definition: rel.h:436
int64 last
Definition: sequence.c:78
#define ereport(elevel, rest)
Definition: elog.h:122
SeqTableData * SeqTable
Definition: sequence.c:85
Oid filenode
Definition: sequence.c:75
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
LocalTransactionId lxid
Definition: sequence.c:76
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define InvalidLocalTransactionId
Definition: lock.h:69
static Relation lock_and_open_sequence(SeqTable seq)
Definition: sequence.c:1048
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Datum lastval ( PG_FUNCTION_ARGS  )

Definition at line 851 of file sequence.c.

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

852 {
853  Relation seqrel;
854  int64 result;
855 
856  if (last_used_seq == NULL)
857  ereport(ERROR,
858  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
859  errmsg("lastval is not yet defined in this session")));
860 
861  /* Someone may have dropped the sequence since the last nextval() */
863  ereport(ERROR,
864  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
865  errmsg("lastval is not yet defined in this session")));
866 
868 
869  /* nextval() must have already been called for this sequence */
871 
874  ereport(ERROR,
875  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
876  errmsg("permission denied for sequence %s",
877  RelationGetRelationName(seqrel))));
878 
879  result = last_used_seq->last;
880  relation_close(seqrel, NoLock);
881 
882  PG_RETURN_INT64(result);
883 }
Oid GetUserId(void)
Definition: miscinit.c:284
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
bool last_valid
Definition: sequence.c:77
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
return result
Definition: formatting.c:1633
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:174
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RelationGetRelationName(relation)
Definition: rel.h:436
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_SELECT
Definition: parsenodes.h:73
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static SeqTableData * last_used_seq
Definition: sequence.c:93
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Relation lock_and_open_sequence(SeqTable seq)
Definition: sequence.c:1048
static Relation lock_and_open_sequence ( SeqTable  seq)
static

Definition at line 1048 of file sequence.c.

References CurrentResourceOwner, LockRelationOid(), SeqTableData::lxid, PGPROC::lxid, MyProc, NoLock, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, relation_open(), SeqTableData::relid, RowExclusiveLock, and TopTransactionResourceOwner.

Referenced by init_sequence(), and lastval().

1049 {
1050  LocalTransactionId thislxid = MyProc->lxid;
1051 
1052  /* Get the lock if not already held in this xact */
1053  if (seq->lxid != thislxid)
1054  {
1055  ResourceOwner currentOwner;
1056 
1057  currentOwner = CurrentResourceOwner;
1058  PG_TRY();
1059  {
1062  }
1063  PG_CATCH();
1064  {
1065  /* Ensure CurrentResourceOwner is restored on error */
1066  CurrentResourceOwner = currentOwner;
1067  PG_RE_THROW();
1068  }
1069  PG_END_TRY();
1070  CurrentResourceOwner = currentOwner;
1071 
1072  /* Flag that we have a lock in the current xact */
1073  seq->lxid = thislxid;
1074  }
1075 
1076  /* We now know we have the lock, and can safely open the rel */
1077  return relation_open(seq->relid, NoLock);
1078 }
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
PGPROC * MyProc
Definition: proc.c:67
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
uint32 LocalTransactionId
Definition: c.h:399
#define PG_CATCH()
Definition: elog.h:293
#define PG_RE_THROW()
Definition: elog.h:314
LocalTransactionId lxid
Definition: sequence.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
LocalTransactionId lxid
Definition: proc.h:105
Datum nextval ( PG_FUNCTION_ARGS  )

Definition at line 539 of file sequence.c.

References makeRangeVarFromNameList(), nextval_internal(), NoLock, PG_GETARG_TEXT_PP, PG_RETURN_INT64, RangeVarGetRelid, and textToQualifiedNameList().

Referenced by autoinc(), and ttdummy().

540 {
541  text *seqin = PG_GETARG_TEXT_PP(0);
542  RangeVar *sequence;
543  Oid relid;
544 
546 
547  /*
548  * XXX: This is not safe in the presence of concurrent DDL, but acquiring
549  * a lock here is more expensive than letting nextval_internal do it,
550  * since the latter maintains a cache that keeps us from hitting the lock
551  * manager more than once per transaction. It's not clear whether the
552  * performance penalty is material in practice, but for now, we do it this
553  * way.
554  */
555  relid = RangeVarGetRelid(sequence, NoLock, false);
556 
557  PG_RETURN_INT64(nextval_internal(relid, true));
558 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:569
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3023
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NoLock
Definition: lockdefs.h:34
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3202
Definition: c.h:439
int64 nextval_internal ( Oid  relid,
bool  check_permissions 
)

Definition at line 569 of file sequence.c.

References ACL_UPDATE, ACL_USAGE, ACLCHECK_OK, Assert, buf, BufferGetPage, SeqTableData::cached, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, GetRedoRecPtr(), GETSTRUCT, GetTopTransactionId(), GetUserId(), HeapTupleIsValid, SeqTableData::increment, init_sequence(), INT64_FORMAT, FormData_pg_sequence_data::is_called, SeqTableData::last, SeqTableData::last_valid, FormData_pg_sequence_data::last_value, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, xl_seq_rec::node, NoLock, ObjectIdGetDatum, PageGetLSN, PageSetLSN, pg_class_aclcheck(), PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RelationData::rd_islocaltemp, RelationData::rd_node, read_seq_tuple(), REGBUF_WILL_INIT, relation_close(), RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, result, SearchSysCache1, SEQ_LOG_VALS, SEQRELID, snprintf(), START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by ExecEvalNextValueExpr(), nextval(), and nextval_oid().

570 {
571  SeqTable elm;
572  Relation seqrel;
573  Buffer buf;
574  Page page;
575  HeapTuple pgstuple;
576  Form_pg_sequence pgsform;
577  HeapTupleData seqdatatuple;
579  int64 incby,
580  maxv,
581  minv,
582  cache,
583  log,
584  fetch,
585  last;
586  int64 result,
587  next,
588  rescnt = 0;
589  bool cycle;
590  bool logit = false;
591 
592  /* open and lock sequence */
593  init_sequence(relid, &elm, &seqrel);
594 
595  if (check_permissions &&
598  ereport(ERROR,
599  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
600  errmsg("permission denied for sequence %s",
601  RelationGetRelationName(seqrel))));
602 
603  /* read-only transactions may only modify temp sequences */
604  if (!seqrel->rd_islocaltemp)
605  PreventCommandIfReadOnly("nextval()");
606 
607  /*
608  * Forbid this during parallel operation because, to make it work, the
609  * cooperating backends would need to share the backend-local cached
610  * sequence information. Currently, we don't support that.
611  */
612  PreventCommandIfParallelMode("nextval()");
613 
614  if (elm->last != elm->cached) /* some numbers were cached */
615  {
616  Assert(elm->last_valid);
617  Assert(elm->increment != 0);
618  elm->last += elm->increment;
619  relation_close(seqrel, NoLock);
620  last_used_seq = elm;
621  return elm->last;
622  }
623 
624  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
625  if (!HeapTupleIsValid(pgstuple))
626  elog(ERROR, "cache lookup failed for sequence %u", relid);
627  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
628  incby = pgsform->seqincrement;
629  maxv = pgsform->seqmax;
630  minv = pgsform->seqmin;
631  cache = pgsform->seqcache;
632  cycle = pgsform->seqcycle;
633  ReleaseSysCache(pgstuple);
634 
635  /* lock page' buffer and read tuple */
636  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
637  page = BufferGetPage(buf);
638 
639  elm->increment = incby;
640  last = next = result = seq->last_value;
641  fetch = cache;
642  log = seq->log_cnt;
643 
644  if (!seq->is_called)
645  {
646  rescnt++; /* return last_value if not is_called */
647  fetch--;
648  }
649 
650  /*
651  * Decide whether we should emit a WAL log record. If so, force up the
652  * fetch count to grab SEQ_LOG_VALS more values than we actually need to
653  * cache. (These will then be usable without logging.)
654  *
655  * If this is the first nextval after a checkpoint, we must force a new
656  * WAL record to be written anyway, else replay starting from the
657  * checkpoint would fail to advance the sequence past the logged values.
658  * In this case we may as well fetch extra values.
659  */
660  if (log < fetch || !seq->is_called)
661  {
662  /* forced log to satisfy local demand for values */
663  fetch = log = fetch + SEQ_LOG_VALS;
664  logit = true;
665  }
666  else
667  {
668  XLogRecPtr redoptr = GetRedoRecPtr();
669 
670  if (PageGetLSN(page) <= redoptr)
671  {
672  /* last update of seq was before checkpoint */
673  fetch = log = fetch + SEQ_LOG_VALS;
674  logit = true;
675  }
676  }
677 
678  while (fetch) /* try to fetch cache [+ log ] numbers */
679  {
680  /*
681  * Check MAXVALUE for ascending sequences and MINVALUE for descending
682  * sequences
683  */
684  if (incby > 0)
685  {
686  /* ascending sequence */
687  if ((maxv >= 0 && next > maxv - incby) ||
688  (maxv < 0 && next + incby > maxv))
689  {
690  if (rescnt > 0)
691  break; /* stop fetching */
692  if (!cycle)
693  {
694  char buf[100];
695 
696  snprintf(buf, sizeof(buf), INT64_FORMAT, maxv);
697  ereport(ERROR,
698  (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
699  errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",
700  RelationGetRelationName(seqrel), buf)));
701  }
702  next = minv;
703  }
704  else
705  next += incby;
706  }
707  else
708  {
709  /* descending sequence */
710  if ((minv < 0 && next < minv - incby) ||
711  (minv >= 0 && next + incby < minv))
712  {
713  if (rescnt > 0)
714  break; /* stop fetching */
715  if (!cycle)
716  {
717  char buf[100];
718 
719  snprintf(buf, sizeof(buf), INT64_FORMAT, minv);
720  ereport(ERROR,
721  (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
722  errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",
723  RelationGetRelationName(seqrel), buf)));
724  }
725  next = maxv;
726  }
727  else
728  next += incby;
729  }
730  fetch--;
731  if (rescnt < cache)
732  {
733  log--;
734  rescnt++;
735  last = next;
736  if (rescnt == 1) /* if it's first result - */
737  result = next; /* it's what to return */
738  }
739  }
740 
741  log -= fetch; /* adjust for any unfetched numbers */
742  Assert(log >= 0);
743 
744  /* save info in local cache */
745  elm->last = result; /* last returned number */
746  elm->cached = last; /* last fetched number */
747  elm->last_valid = true;
748 
749  last_used_seq = elm;
750 
751  /*
752  * If something needs to be WAL logged, acquire an xid, so this
753  * transaction's commit will trigger a WAL flush and wait for syncrep.
754  * It's sufficient to ensure the toplevel transaction has an xid, no need
755  * to assign xids subxacts, that'll already trigger an appropriate wait.
756  * (Have to do that here, so we're outside the critical section)
757  */
758  if (logit && RelationNeedsWAL(seqrel))
760 
761  /* ready to change the on-disk (or really, in-buffer) tuple */
763 
764  /*
765  * We must mark the buffer dirty before doing XLogInsert(); see notes in
766  * SyncOneBuffer(). However, we don't apply the desired changes just yet.
767  * This looks like a violation of the buffer update protocol, but it is in
768  * fact safe because we hold exclusive lock on the buffer. Any other
769  * process, including a checkpoint, that tries to examine the buffer
770  * contents will block until we release the lock, and then will see the
771  * final state that we install below.
772  */
773  MarkBufferDirty(buf);
774 
775  /* XLOG stuff */
776  if (logit && RelationNeedsWAL(seqrel))
777  {
778  xl_seq_rec xlrec;
779  XLogRecPtr recptr;
780 
781  /*
782  * We don't log the current state of the tuple, but rather the state
783  * as it would appear after "log" more fetches. This lets us skip
784  * that many future WAL records, at the cost that we lose those
785  * sequence values if we crash.
786  */
787  XLogBeginInsert();
789 
790  /* set values that will be saved in xlog */
791  seq->last_value = next;
792  seq->is_called = true;
793  seq->log_cnt = 0;
794 
795  xlrec.node = seqrel->rd_node;
796 
797  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
798  XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
799 
800  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
801 
802  PageSetLSN(page, recptr);
803  }
804 
805  /* Now update sequence tuple to the intended final state */
806  seq->last_value = last; /* last fetched number */
807  seq->is_called = true;
808  seq->log_cnt = log; /* how much is logged */
809 
811 
812  UnlockReleaseBuffer(buf);
813 
814  relation_close(seqrel, NoLock);
815 
816  return result;
817 }
int64 cached
Definition: sequence.c:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static int32 next
Definition: blutils.c:210
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:254
Oid GetUserId(void)
Definition: miscinit.c:284
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
bool last_valid
Definition: sequence.c:77
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
static void check_permissions(void)
Definition: logicalfuncs.c:109
bool rd_islocaltemp
Definition: rel.h:90
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
return result
Definition: formatting.c:1633
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
RelFileNode node
Definition: sequence.h:50
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
HeapTupleHeader t_data
Definition: htup.h:67
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
uint32 t_len
Definition: htup.h:64
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define RelationGetRelationName(relation)
Definition: rel.h:436
int64 last
Definition: sequence.c:78
#define ACL_USAGE
Definition: parsenodes.h:80
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1168
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define ACL_UPDATE
Definition: parsenodes.h:74
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:676
#define SEQ_LOG_VALS
Definition: sequence.c:54
int64 increment
Definition: sequence.c:81
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8168
#define RelationNeedsWAL(relation)
Definition: rel.h:505
#define INT64_FORMAT
Definition: c.h:315
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:236
static SeqTableData * last_used_seq
Definition: sequence.c:93
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
#define PageGetLSN(page)
Definition: bufpage.h:362
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
Datum nextval_oid ( PG_FUNCTION_ARGS  )

Definition at line 561 of file sequence.c.

References nextval_internal(), PG_GETARG_OID, and PG_RETURN_INT64.

562 {
563  Oid relid = PG_GETARG_OID(0);
564 
565  PG_RETURN_INT64(nextval_internal(relid, true));
566 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:569
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
Datum pg_sequence_last_value ( PG_FUNCTION_ARGS  )

Definition at line 1838 of file sequence.c.

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, buf, ereport, errcode(), errmsg(), ERROR, GetUserId(), init_sequence(), FormData_pg_sequence_data::is_called, FormData_pg_sequence_data::last_value, NoLock, pg_class_aclcheck(), PG_GETARG_OID, PG_RETURN_INT64, PG_RETURN_NULL, read_seq_tuple(), relation_close(), RelationGetRelationName, result, and UnlockReleaseBuffer().

1839 {
1840  Oid relid = PG_GETARG_OID(0);
1841  SeqTable elm;
1842  Relation seqrel;
1843  Buffer buf;
1844  HeapTupleData seqtuple;
1846  bool is_called;
1847  int64 result;
1848 
1849  /* open and lock sequence */
1850  init_sequence(relid, &elm, &seqrel);
1851 
1853  ereport(ERROR,
1854  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1855  errmsg("permission denied for sequence %s",
1856  RelationGetRelationName(seqrel))));
1857 
1858  seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1859 
1860  is_called = seq->is_called;
1861  result = seq->last_value;
1862 
1863  UnlockReleaseBuffer(buf);
1864  relation_close(seqrel, NoLock);
1865 
1866  if (is_called)
1867  PG_RETURN_INT64(result);
1868  else
1869  PG_RETURN_NULL();
1870 }
Oid GetUserId(void)
Definition: miscinit.c:284
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
return result
Definition: formatting.c:1633
unsigned int Oid
Definition: postgres_ext.h:31
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1168
#define ACL_SELECT
Definition: parsenodes.h:73
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
int errmsg(const char *fmt,...)
Definition: elog.c:797
int Buffer
Definition: buf.h:23
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum pg_sequence_parameters ( PG_FUNCTION_ARGS  )

Definition at line 1779 of file sequence.c.

References ACL_SELECT, ACL_UPDATE, ACL_USAGE, ACLCHECK_OK, BlessTupleDesc(), BoolGetDatum, BOOLOID, CreateTemplateTupleDesc(), elog, ereport, errcode(), errmsg(), ERROR, get_rel_name(), GETSTRUCT, GetUserId(), heap_form_tuple(), HeapTupleGetDatum, HeapTupleIsValid, Int64GetDatum(), INT8OID, ObjectIdGetDatum, OIDOID, pg_class_aclcheck(), PG_GETARG_OID, ReleaseSysCache(), SearchSysCache1, SEQRELID, TupleDescInitEntry(), and values.

1780 {
1781  Oid relid = PG_GETARG_OID(0);
1782  TupleDesc tupdesc;
1783  Datum values[7];
1784  bool isnull[7];
1785  HeapTuple pgstuple;
1786  Form_pg_sequence pgsform;
1787 
1789  ereport(ERROR,
1790  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1791  errmsg("permission denied for sequence %s",
1792  get_rel_name(relid))));
1793 
1794  tupdesc = CreateTemplateTupleDesc(7, false);
1795  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
1796  INT8OID, -1, 0);
1797  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
1798  INT8OID, -1, 0);
1799  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value",
1800  INT8OID, -1, 0);
1801  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment",
1802  INT8OID, -1, 0);
1803  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option",
1804  BOOLOID, -1, 0);
1805  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size",
1806  INT8OID, -1, 0);
1807  TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type",
1808  OIDOID, -1, 0);
1809 
1810  BlessTupleDesc(tupdesc);
1811 
1812  memset(isnull, 0, sizeof(isnull));
1813 
1814  pgstuple = SearchSysCache1(SEQRELID, relid);
1815  if (!HeapTupleIsValid(pgstuple))
1816  elog(ERROR, "cache lookup failed for sequence %u", relid);
1817  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1818 
1819  values[0] = Int64GetDatum(pgsform->seqstart);
1820  values[1] = Int64GetDatum(pgsform->seqmin);
1821  values[2] = Int64GetDatum(pgsform->seqmax);
1822  values[3] = Int64GetDatum(pgsform->seqincrement);
1823  values[4] = BoolGetDatum(pgsform->seqcycle);
1824  values[5] = Int64GetDatum(pgsform->seqcache);
1825  values[6] = ObjectIdGetDatum(pgsform->seqtypid);
1826 
1827  ReleaseSysCache(pgstuple);
1828 
1829  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
1830 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:284
#define OIDOID
Definition: pg_type.h:328
int errcode(int sqlerrcode)
Definition: elog.c:575
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
#define ACL_USAGE
Definition: parsenodes.h:80
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:497
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_UPDATE
Definition: parsenodes.h:74
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define ACL_SELECT
Definition: parsenodes.h:73
#define BoolGetDatum(X)
Definition: postgres.h:408
#define INT8OID
Definition: pg_type.h:304
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define BOOLOID
Definition: pg_type.h:288
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4422
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
int16 AttrNumber
Definition: attnum.h:21
static void process_owned_by ( Relation  seqrel,
List owned_by,
bool  for_identity 
)
static

Definition at line 1639 of file sequence.c.

References AccessShareLock, Assert, ObjectAddress::classId, deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, get_attnum(), get_rel_name(), InvalidAttrNumber, lfirst, linitial, list_copy(), list_length(), list_tail(), list_truncate(), makeRangeVarFromNameList(), NoLock, NULL, ObjectAddress::objectId, ObjectAddress::objectSubId, RelationData::rd_rel, recordDependencyOn(), relation_close(), relation_openrv(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RelationRelationId, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, sequenceIsOwned(), and strVal.

Referenced by AlterSequence(), and DefineSequence().

1640 {
1641  DependencyType deptype;
1642  int nnames;
1643  Relation tablerel;
1644  AttrNumber attnum;
1645 
1646  deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO;
1647 
1648  nnames = list_length(owned_by);
1649  Assert(nnames > 0);
1650  if (nnames == 1)
1651  {
1652  /* Must be OWNED BY NONE */
1653  if (strcmp(strVal(linitial(owned_by)), "none") != 0)
1654  ereport(ERROR,
1655  (errcode(ERRCODE_SYNTAX_ERROR),
1656  errmsg("invalid OWNED BY option"),
1657  errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
1658  tablerel = NULL;
1659  attnum = 0;
1660  }
1661  else
1662  {
1663  List *relname;
1664  char *attrname;
1665  RangeVar *rel;
1666 
1667  /* Separate relname and attr name */
1668  relname = list_truncate(list_copy(owned_by), nnames - 1);
1669  attrname = strVal(lfirst(list_tail(owned_by)));
1670 
1671  /* Open and lock rel to ensure it won't go away meanwhile */
1672  rel = makeRangeVarFromNameList(relname);
1673  tablerel = relation_openrv(rel, AccessShareLock);
1674 
1675  /* Must be a regular or foreign table */
1676  if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
1677  tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1678  tablerel->rd_rel->relkind == RELKIND_VIEW ||
1679  tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1680  ereport(ERROR,
1681  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1682  errmsg("referenced relation \"%s\" is not a table or foreign table",
1683  RelationGetRelationName(tablerel))));
1684 
1685  /* We insist on same owner and schema */
1686  if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
1687  ereport(ERROR,
1688  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1689  errmsg("sequence must have same owner as table it is linked to")));
1690  if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
1691  ereport(ERROR,
1692  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1693  errmsg("sequence must be in same schema as table it is linked to")));
1694 
1695  /* Now, fetch the attribute number from the system cache */
1696  attnum = get_attnum(RelationGetRelid(tablerel), attrname);
1697  if (attnum == InvalidAttrNumber)
1698  ereport(ERROR,
1699  (errcode(ERRCODE_UNDEFINED_COLUMN),
1700  errmsg("column \"%s\" of relation \"%s\" does not exist",
1701  attrname, RelationGetRelationName(tablerel))));
1702  }
1703 
1704  /*
1705  * Catch user explicitly running OWNED BY on identity sequence.
1706  */
1707  if (deptype == DEPENDENCY_AUTO)
1708  {
1709  Oid tableId;
1710  int32 colId;
1711 
1712  if (sequenceIsOwned(RelationGetRelid(seqrel), DEPENDENCY_INTERNAL, &tableId, &colId))
1713  ereport(ERROR,
1714  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1715  errmsg("cannot change ownership of identity sequence"),
1716  errdetail("Sequence \"%s\" is linked to table \"%s\".",
1717  RelationGetRelationName(seqrel),
1718  get_rel_name(tableId))));
1719  }
1720 
1721  /*
1722  * OK, we are ready to update pg_depend. First remove any existing
1723  * dependencies for the sequence, then optionally add a new one.
1724  */
1726  RelationRelationId, deptype);
1727 
1728  if (tablerel)
1729  {
1730  ObjectAddress refobject,
1731  depobject;
1732 
1733  refobject.classId = RelationRelationId;
1734  refobject.objectId = RelationGetRelid(tablerel);
1735  refobject.objectSubId = attnum;
1736  depobject.classId = RelationRelationId;
1737  depobject.objectId = RelationGetRelid(seqrel);
1738  depobject.objectSubId = 0;
1739  recordDependencyOn(&depobject, &refobject, deptype);
1740  }
1741 
1742  /* Done, but hold lock until commit */
1743  if (tablerel)
1744  relation_close(tablerel, NoLock);
1745 }
DependencyType
Definition: dependency.h:73
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1198
int errhint(const char *fmt,...)
Definition: elog.c:987
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
#define RelationRelationId
Definition: pg_class.h:29
List * list_truncate(List *list, int new_size)
Definition: list.c:350
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3023
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
static ListCell * list_tail(List *l)
Definition: pg_list.h:83
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:164
#define RELKIND_RELATION
Definition: pg_class.h:160
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:416
#define RelationGetNamespace(relation)
Definition: rel.h:443
static Form_pg_sequence_data read_seq_tuple ( Relation  rel,
Buffer buf,
HeapTuple  seqdatatuple 
)
static

Definition at line 1168 of file sequence.c.

References Assert, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, elog, ERROR, FirstOffsetNumber, GETSTRUCT, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HeapTupleHeaderGetRawXmax, HeapTupleHeaderSetXmax, InvalidTransactionId, ItemIdGetLength, ItemIdIsNormal, LockBuffer(), sequence_magic::magic, MarkBufferDirtyHint(), PageGetItem, PageGetItemId, PageGetSpecialPointer, ReadBuffer(), RelationGetRelationName, SEQ_MAGIC, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, and HeapTupleData::t_len.

Referenced by AlterSequence(), do_setval(), nextval_internal(), pg_sequence_last_value(), and ResetSequence().

1169 {
1170  Page page;
1171  ItemId lp;
1172  sequence_magic *sm;
1174 
1175  *buf = ReadBuffer(rel, 0);
1177 
1178  page = BufferGetPage(*buf);
1179  sm = (sequence_magic *) PageGetSpecialPointer(page);
1180 
1181  if (sm->magic != SEQ_MAGIC)
1182  elog(ERROR, "bad magic number in sequence \"%s\": %08X",
1183  RelationGetRelationName(rel), sm->magic);
1184 
1185  lp = PageGetItemId(page, FirstOffsetNumber);
1186  Assert(ItemIdIsNormal(lp));
1187 
1188  /* Note we currently only bother to set these two fields of *seqdatatuple */
1189  seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1190  seqdatatuple->t_len = ItemIdGetLength(lp);
1191 
1192  /*
1193  * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1194  * a sequence, which would leave a non-frozen XID in the sequence tuple's
1195  * xmax, which eventually leads to clog access failures or worse. If we
1196  * see this has happened, clean up after it. We treat this like a hint
1197  * bit update, ie, don't bother to WAL-log it, since we can certainly do
1198  * this again if the update gets lost.
1199  */
1200  Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
1202  {
1204  seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
1205  seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
1206  MarkBufferDirtyHint(*buf, true);
1207  }
1208 
1209  seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
1210 
1211  return seq;
1212 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SEQ_MAGIC
Definition: sequence.c:59
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
uint32 t_len
Definition: htup.h:64
static char * buf
Definition: pg_test_fsync.c:66
#define FirstOffsetNumber
Definition: off.h:27
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define Assert(condition)
Definition: c.h:676
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint32 magic
Definition: sequence.c:63
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define elog
Definition: elog.h:219
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
Pointer Page
Definition: bufpage.h:74
void ResetSequence ( Oid  seq_relid)

Definition at line 269 of file sequence.c.

References buf, SeqTableData::cached, elog, ERROR, fill_seq_with_data(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, init_sequence(), InvalidMultiXactId, InvalidTransactionId, FormData_pg_sequence_data::is_called, SeqTableData::last, FormData_pg_sequence_data::last_value, FormData_pg_sequence_data::log_cnt, NoLock, ObjectIdGetDatum, RelationData::rd_rel, read_seq_tuple(), relation_close(), RelationSetNewRelfilenode(), ReleaseSysCache(), SearchSysCache1, SEQRELID, and UnlockReleaseBuffer().

Referenced by ExecuteTruncate().

270 {
271  Relation seq_rel;
272  SeqTable elm;
274  Buffer buf;
275  HeapTupleData seqdatatuple;
276  HeapTuple tuple;
277  HeapTuple pgstuple;
278  Form_pg_sequence pgsform;
279  int64 startv;
280 
281  /*
282  * Read the old sequence. This does a bit more work than really
283  * necessary, but it's simple, and we do want to double-check that it's
284  * indeed a sequence.
285  */
286  init_sequence(seq_relid, &elm, &seq_rel);
287  (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
288 
289  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
290  if (!HeapTupleIsValid(pgstuple))
291  elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
292  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
293  startv = pgsform->seqstart;
294  ReleaseSysCache(pgstuple);
295 
296  /*
297  * Copy the existing sequence tuple.
298  */
299  tuple = heap_copytuple(&seqdatatuple);
300 
301  /* Now we're done with the old page */
302  UnlockReleaseBuffer(buf);
303 
304  /*
305  * Modify the copied tuple to execute the restart (compare the RESTART
306  * action in AlterSequence)
307  */
308  seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
309  seq->last_value = startv;
310  seq->is_called = false;
311  seq->log_cnt = 0;
312 
313  /*
314  * Create a new storage file for the sequence. We want to keep the
315  * sequence's relfrozenxid at 0, since it won't contain any unfrozen XIDs.
316  * Same with relminmxid, since a sequence will never contain multixacts.
317  */
318  RelationSetNewRelfilenode(seq_rel, seq_rel->rd_rel->relpersistence,
320 
321  /*
322  * Insert the modified tuple into the new storage file.
323  */
324  fill_seq_with_data(seq_rel, tuple);
325 
326  /* Clear local cache so that we don't think we have cached numbers */
327  /* Note that we do not change the currval() state */
328  elm->cached = elm->last;
329 
330  relation_close(seq_rel, NoLock);
331 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
int64 cached
Definition: sequence.c:79
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3422
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
Form_pg_class rd_rel
Definition: rel.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
#define InvalidTransactionId
Definition: transam.h:31
int64 last
Definition: sequence.c:78
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1168
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define InvalidMultiXactId
Definition: multixact.h:23
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1101
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:337
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
void ResetSequenceCaches ( void  )

Definition at line 1927 of file sequence.c.

References hash_destroy(), and NULL.

Referenced by DiscardAll(), and DiscardCommand().

1928 {
1929  if (seqhashtab)
1930  {
1932  seqhashtab = NULL;
1933  }
1934 
1935  last_used_seq = NULL;
1936 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:810
static HTAB * seqhashtab
Definition: sequence.c:87
#define NULL
Definition: c.h:229
static SeqTableData * last_used_seq
Definition: sequence.c:93
void seq_mask ( char *  page,
BlockNumber  blkno 
)

Definition at line 1942 of file sequence.c.

References mask_page_lsn(), and mask_unused_space().

1943 {
1944  mask_page_lsn(page);
1945 
1946  mask_unused_space(page);
1947 }
void mask_unused_space(Page page)
Definition: bufmask.c:69
void mask_page_lsn(Page page)
Definition: bufmask.c:30
void seq_redo ( XLogReaderState record)

Definition at line 1874 of file sequence.c.

References buffer, BufferGetPage, BufferGetPageSize, elog, XLogReaderState::EndRecPtr, FirstOffsetNumber, InvalidOffsetNumber, sequence_magic::magic, MarkBufferDirty(), PageAddItem, PageGetSpecialPointer, PageInit(), PageSetLSN, palloc(), PANIC, pfree(), SEQ_MAGIC, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogInitBufferForRedo(), XLogRecGetData, XLogRecGetDataLen, XLogRecGetInfo, and XLR_INFO_MASK.

1875 {
1876  XLogRecPtr lsn = record->EndRecPtr;
1877  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1878  Buffer buffer;
1879  Page page;
1880  Page localpage;
1881  char *item;
1882  Size itemsz;
1883  xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1884  sequence_magic *sm;
1885 
1886  if (info != XLOG_SEQ_LOG)
1887  elog(PANIC, "seq_redo: unknown op code %u", info);
1888 
1889  buffer = XLogInitBufferForRedo(record, 0);
1890  page = (Page) BufferGetPage(buffer);
1891 
1892  /*
1893  * We always reinit the page. However, since this WAL record type is also
1894  * used for updating sequences, it's possible that a hot-standby backend
1895  * is examining the page concurrently; so we mustn't transiently trash the
1896  * buffer. The solution is to build the correct new page contents in
1897  * local workspace and then memcpy into the buffer. Then only bytes that
1898  * are supposed to change will change, even transiently. We must palloc
1899  * the local page for alignment reasons.
1900  */
1901  localpage = (Page) palloc(BufferGetPageSize(buffer));
1902 
1903  PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1904  sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1905  sm->magic = SEQ_MAGIC;
1906 
1907  item = (char *) xlrec + sizeof(xl_seq_rec);
1908  itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1909 
1910  if (PageAddItem(localpage, (Item) item, itemsz,
1911  FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1912  elog(PANIC, "seq_redo: failed to add item to page");
1913 
1914  PageSetLSN(localpage, lsn);
1915 
1916  memcpy(page, localpage, BufferGetPageSize(buffer));
1917  MarkBufferDirty(buffer);
1918  UnlockReleaseBuffer(buffer);
1919 
1920  pfree(localpage);
1921 }
#define SEQ_MAGIC
Definition: sequence.c:59
struct xl_seq_rec xl_seq_rec
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
unsigned char uint8
Definition: c.h:266
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
#define PANIC
Definition: elog.h:53
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
void pfree(void *pointer)
Definition: mcxt.c:950
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:221
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
#define FirstOffsetNumber
Definition: off.h:27
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:216
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define InvalidOffsetNumber
Definition: off.h:26
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
uint32 magic
Definition: sequence.c:63
size_t Size
Definition: c.h:356
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
#define XLOG_SEQ_LOG
Definition: sequence.h:46
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
List* sequence_options ( Oid  relid)

Definition at line 1752 of file sequence.c.

References elog, ERROR, GETSTRUCT, HeapTupleIsValid, lappend(), makeDefElem(), makeInteger(), NIL, options, ReleaseSysCache(), SearchSysCache1, and SEQRELID.

Referenced by transformTableLikeClause().

1753 {
1754  HeapTuple pgstuple;
1755  Form_pg_sequence pgsform;
1756  List *options = NIL;
1757 
1758  pgstuple = SearchSysCache1(SEQRELID, relid);
1759  if (!HeapTupleIsValid(pgstuple))
1760  elog(ERROR, "cache lookup failed for sequence %u", relid);
1761  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1762 
1763  options = lappend(options, makeDefElem("cache", (Node *) makeInteger(pgsform->seqcache), -1));
1764  options = lappend(options, makeDefElem("cycle", (Node *) makeInteger(pgsform->seqcycle), -1));
1765  options = lappend(options, makeDefElem("increment", (Node *) makeInteger(pgsform->seqincrement), -1));
1766  options = lappend(options, makeDefElem("maxvalue", (Node *) makeInteger(pgsform->seqmax), -1));
1767  options = lappend(options, makeDefElem("minvalue", (Node *) makeInteger(pgsform->seqmin), -1));
1768  options = lappend(options, makeDefElem("start", (Node *) makeInteger(pgsform->seqstart), -1));
1769 
1770  ReleaseSysCache(pgstuple);
1771 
1772  return options;
1773 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: nodes.h:509
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:20
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:544
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
Value * makeInteger(long i)
Definition: value.c:23
#define ERROR
Definition: elog.h:43
List * lappend(List *list, void *datum)
Definition: list.c:128
static char ** options
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Datum setval3_oid ( PG_FUNCTION_ARGS  )

Definition at line 1027 of file sequence.c.

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

1028 {
1029  Oid relid = PG_GETARG_OID(0);
1030  int64 next = PG_GETARG_INT64(1);
1031  bool iscalled = PG_GETARG_BOOL(2);
1032 
1033  do_setval(relid, next, iscalled);
1034 
1035  PG_RETURN_INT64(next);
1036 }
static int32 next
Definition: blutils.c:210
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:899
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
Datum setval_oid ( PG_FUNCTION_ARGS  )

Definition at line 1012 of file sequence.c.

References do_setval(), next, PG_GETARG_INT64, PG_GETARG_OID, and PG_RETURN_INT64.

1013 {
1014  Oid relid = PG_GETARG_OID(0);
1015  int64 next = PG_GETARG_INT64(1);
1016 
1017  do_setval(relid, next, true);
1018 
1019  PG_RETURN_INT64(next);
1020 }
static int32 next
Definition: blutils.c:210
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:899
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247

Variable Documentation

SeqTableData* last_used_seq = NULL
static

Definition at line 93 of file sequence.c.

HTAB* seqhashtab = NULL
static

Definition at line 87 of file sequence.c.