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