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