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