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