添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2 *
3 * sequence.c
4 * PostgreSQL sequences support code.
5 *
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/commands/sequence.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 #include " postgres.h "
17 #include " access/bufmask.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 "
28 #include " catalog/indexing.h "
29 #include " catalog/namespace.h "
32 #include " catalog/pg_type.h "
34 #include " commands/defrem.h "
35 #include " commands/sequence.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 "
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
59 /*
60 * The "special area" of a sequence's buffer page looks like this.
61 */
62 #define SEQ_MAGIC 0x1717
65 {
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() */
90 static HTAB * seqhashtab = NULL; /* hash table for SeqTable items */
92 /*
93 * last_used_seq is updated by nextval() to point to the last used
94 * sequence.
95 */
101 static void create_seq_hashtable ( void );
102 static void init_sequence ( Oid relid, SeqTable *p_elm, Relation *p_rel);
104 Buffer * buf , HeapTuple seqdatatuple);
105 static void init_params ( ParseState *pstate, List * options , bool for_identity,
106 bool isInit,
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);
115 /*
116 * DefineSequence
117 * Creates a new sequence relation
118 */
121 {
124 bool need_seq_rewrite;
125 List *owned_by;
127 Oid seqoid;
128 ObjectAddress address;
129 Relation rel;
130 HeapTuple tuple;
131 TupleDesc tupDesc;
133 bool null [ SEQ_COL_LASTCOL ];
134 Datum pgs_values[Natts_pg_sequence];
135 bool pgs_nulls[Natts_pg_sequence];
136 int i ;
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 if (seq-> if_not_exists )
144 {
146 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 ObjectAddressSet (address, RelationRelationId, seqoid);
155 /* OK to skip */
157 ( errcode (ERRCODE_DUPLICATE_TABLE),
158 errmsg ( "relation \"%s\" already exists, skipping" ,
159 seq-> sequence -> relname )));
161 }
162 }
164 /* Check and set all option values */
165 init_params (pstate, seq-> options , seq-> for_identity , true ,
166 &seqform, &seqdataform,
167 &need_seq_rewrite, &owned_by);
169 /*
170 * Create relation (and fill value[] and null[] for the tuple)
171 */
172 stmt ->tableElts = NIL ;
174 {
175 ColumnDef *coldef;
177 switch ( i )
178 {
180 coldef = makeColumnDef ( "last_value" , INT8OID, -1, InvalidOid );
182 break ;
183 case SEQ_COL_LOG :
184 coldef = makeColumnDef ( "log_cnt" , INT8OID, -1, InvalidOid );
185 value [ i - 1] = Int64GetDatum ((int64) 0);
186 break ;
188 coldef = makeColumnDef ( "is_called" , BOOLOID, -1, InvalidOid );
189 value [ i - 1] = BoolGetDatum ( false );
190 break ;
191 }
193 coldef-> is_not_null = true ;
194 null [ i - 1] = false ;
196 stmt ->tableElts = lappend ( stmt ->tableElts, coldef);
197 }
199 stmt ->relation = seq-> sequence ;
200 stmt ->inhRelations = NIL ;
201 stmt ->constraints = NIL ;
202 stmt ->options = NIL ;
203 stmt ->oncommit = ONCOMMIT_NOOP ;
204 stmt ->tablespacename = NULL;
205 stmt ->if_not_exists = seq-> if_not_exists ;
207 address = DefineRelation ( stmt , RELKIND_SEQUENCE, seq-> ownerId , NULL, NULL);
208 seqoid = address. objectId ;
209 Assert (seqoid != InvalidOid );
212 tupDesc = RelationGetDescr (rel);
214 /* now initialize the sequence's data */
215 tuple = heap_form_tuple (tupDesc, value , null );
216 fill_seq_with_data (rel, tuple);
218 /* process OWNED BY if given */
219 if (owned_by)
220 process_owned_by (rel, owned_by, seq-> for_identity );
224 /* fill in pg_sequence */
225 rel = table_open (SequenceRelationId, RowExclusiveLock );
226 tupDesc = RelationGetDescr (rel);
228 memset(pgs_nulls, 0, sizeof (pgs_nulls));
230 pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum (seqoid);
231 pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum (seqform.seqtypid);
232 pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast (seqform.seqstart);
233 pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast (seqform.seqincrement);
234 pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast (seqform.seqmax);
235 pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast (seqform.seqmin);
236 pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast (seqform.seqcache);
237 pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum (seqform.seqcycle);
239 tuple = heap_form_tuple (tupDesc, pgs_values, pgs_nulls);
240 CatalogTupleInsert (rel, tuple);
242 heap_freetuple (tuple);
245 return address;
246 }
248 /*
249 * Reset a sequence to its initial value.
250 *
251 * The change is made transactionally, so that on failure of the current
252 * transaction, the sequence will be restored to its previous state.
253 * We do that by creating a whole new relfilenumber for the sequence; so this
254 * works much like the rewriting forms of ALTER TABLE.
255 *
256 * Caller is assumed to have acquired AccessExclusiveLock on the sequence,
257 * which must not be released until end of transaction. Caller is also
258 * responsible for permissions checking.
259 */
260 void
262 {
263 Relation seq_rel;
264 SeqTable elm;
267 HeapTupleData seqdatatuple;
268 HeapTuple tuple;
269 HeapTuple pgstuple;
271 int64 startv;
273 /*
274 * Read the old sequence. This does a bit more work than really
275 * necessary, but it's simple, and we do want to double-check that it's
276 * indeed a sequence.
277 */
278 init_sequence (seq_relid, &elm, &seq_rel);
279 (void) read_seq_tuple (seq_rel, & buf , &seqdatatuple);
282 if (! HeapTupleIsValid (pgstuple))
283 elog ( ERROR , "cache lookup failed for sequence %u" , seq_relid);
284 pgsform = ( Form_pg_sequence ) GETSTRUCT (pgstuple);
285 startv = pgsform->seqstart;
286 ReleaseSysCache (pgstuple);
288 /*
289 * Copy the existing sequence tuple.
290 */
291 tuple = heap_copytuple (&seqdatatuple);
293 /* Now we're done with the old page */
296 /*
297 * Modify the copied tuple to execute the restart (compare the RESTART
298 * action in AlterSequence)
299 */
301 seq-> last_value = startv;
302 seq-> is_called = false ;
303 seq-> log_cnt = 0;
305 /*
306 * Create a new storage file for the sequence.
307 */
308 RelationSetNewRelfilenumber (seq_rel, seq_rel-> rd_rel ->relpersistence);
310 /*
311 * Ensure sequence's relfrozenxid is at 0, since it won't contain any
312 * unfrozen XIDs. Same with relminmxid, since a sequence will never
313 * contain multixacts.
314 */
315 Assert (seq_rel-> rd_rel ->relfrozenxid == InvalidTransactionId );
316 Assert (seq_rel-> rd_rel ->relminmxid == InvalidMultiXactId );
318 /*
319 * Insert the modified tuple into the new storage file.
320 */
321 fill_seq_with_data (seq_rel, tuple);
323 /* Clear local cache so that we don't think we have cached numbers */
324 /* Note that we do not change the currval() state */
325 elm-> cached = elm-> last ;
328 }
330 /*
331 * Initialize a sequence's relation with the specified tuple as content
332 *
333 * This handles unlogged sequences by writing to both the main and the init
334 * fork as necessary.
335 */
336 static void
338 {
341 if (rel-> rd_rel ->relpersistence == RELPERSISTENCE_UNLOGGED)
342 {
346 smgrcreate (srel, INIT_FORKNUM , false );
350 smgrclose (srel);
351 }
352 }
354 /*
355 * Initialize a sequence's relation fork with the specified tuple as content
356 */
357 static void
359 {
361 Page page;
363 OffsetNumber offnum;
365 /* Initialize first page of relation with special magic number */
367 buf = ExtendBufferedRel ( BMR_REL (rel), forkNum, NULL,
371 page = BufferGetPage ( buf );
377 /* Now insert sequence tuple */
379 /*
380 * Since VACUUM does not process sequences, we have to force the tuple to
381 * have xmin = FrozenTransactionId now. Otherwise it would become
382 * invisible to SELECTs after 2G transactions. It is okay to do this
383 * because if the current transaction aborts, no other xact will ever
384 * examine the sequence tuple anyway.
385 */
391 ItemPointerSet (&tuple-> t_data -> t_ctid , 0, FirstOffsetNumber );
393 /* check the comment above nextval_internal()'s equivalent call. */
394 if ( RelationNeedsWAL (rel))
401 offnum = PageAddItem (page, ( Item ) tuple-> t_data , tuple-> t_len ,
402 InvalidOffsetNumber , false , false );
403 if (offnum != FirstOffsetNumber )
404 elog ( ERROR , "failed to add sequence tuple to page" );
406 /* XLOG stuff */
407 if ( RelationNeedsWAL (rel) || forkNum == INIT_FORKNUM )
408 {
409 xl_seq_rec xlrec;
410 XLogRecPtr recptr;
415 xlrec. locator = rel-> rd_locator ;
417 XLogRegisterData (( char *) &xlrec, sizeof ( xl_seq_rec ));
418 XLogRegisterData (( char *) tuple-> t_data , tuple-> t_len );
420 recptr = XLogInsert (RM_SEQ_ID, XLOG_SEQ_LOG );
422 PageSetLSN (page, recptr);
423 }
428 }
430 /*
431 * AlterSequence
432 *
433 * Modify the definition of a sequence relation
434 */
437 {
438 Oid relid;
439 SeqTable elm;
440 Relation seqrel;
442 HeapTupleData datatuple;
444 Form_pg_sequence_data newdataform;
445 bool need_seq_rewrite;
446 List *owned_by;
447 ObjectAddress address;
448 Relation rel;
449 HeapTuple seqtuple;
450 HeapTuple newdatatuple;
452 /* Open and lock sequence, and check for ownership along the way. */
453 relid = RangeVarGetRelidExtended ( stmt ->sequence,
455 stmt ->missing_ok ? RVR_MISSING_OK : 0,
457 NULL);
458 if (relid == InvalidOid )
459 {
461 ( errmsg ( "relation \"%s\" does not exist, skipping" ,
462 stmt ->sequence->relname)));
464 }
466 init_sequence (relid, &elm, &seqrel);
468 rel = table_open (SequenceRelationId, RowExclusiveLock );
470 ObjectIdGetDatum (relid));
471 if (! HeapTupleIsValid (seqtuple))
472 elog ( ERROR , "cache lookup failed for sequence %u" ,
473 relid);
475 seqform = ( Form_pg_sequence ) GETSTRUCT (seqtuple);
477 /* lock page's buffer and read tuple into new sequence structure */
478 (void) read_seq_tuple (seqrel, & buf , &datatuple);
480 /* copy the existing sequence data tuple, so it can be modified locally */
481 newdatatuple = heap_copytuple (&datatuple);
482 newdataform = ( Form_pg_sequence_data ) GETSTRUCT (newdatatuple);
486 /* Check and set new values */
487 init_params (pstate, stmt ->options, stmt ->for_identity, false ,
488 seqform, newdataform,
489 &need_seq_rewrite, &owned_by);
491 /* Clear local cache so that we don't think we have cached numbers */
492 /* Note that we do not change the currval() state */
493 elm-> cached = elm-> last ;
495 /* If needed, rewrite the sequence relation itself */
496 if (need_seq_rewrite)
497 {
498 /* check the comment above nextval_internal()'s equivalent call. */
499 if ( RelationNeedsWAL (seqrel))
502 /*
503 * Create a new storage file for the sequence, making the state
504 * changes transactional.
505 */
506 RelationSetNewRelfilenumber (seqrel, seqrel-> rd_rel ->relpersistence);
508 /*
509 * Ensure sequence's relfrozenxid is at 0, since it won't contain any
510 * unfrozen XIDs. Same with relminmxid, since a sequence will never
511 * contain multixacts.
512 */
513 Assert (seqrel-> rd_rel ->relfrozenxid == InvalidTransactionId );
514 Assert (seqrel-> rd_rel ->relminmxid == InvalidMultiXactId );
516 /*
517 * Insert the modified tuple into the new storage file.
518 */
519 fill_seq_with_data (seqrel, newdatatuple);
520 }
522 /* process OWNED BY if given */
523 if (owned_by)
524 process_owned_by (seqrel, owned_by, stmt ->for_identity);
526 /* update the pg_sequence tuple (we could skip this in some cases...) */
527 CatalogTupleUpdate (rel, &seqtuple-> t_self , seqtuple);
529 InvokeObjectPostAlterHook (RelationRelationId, relid, 0);
531 ObjectAddressSet (address, RelationRelationId, relid);
536 return address;
537 }
539 void
540 SequenceChangePersistence ( Oid relid, char newrelpersistence)
541 {
542 SeqTable elm;
543 Relation seqrel;
545 HeapTupleData seqdatatuple;
547 init_sequence (relid, &elm, &seqrel);
549 /* check the comment above nextval_internal()'s equivalent call. */
550 if ( RelationNeedsWAL (seqrel))
553 (void) read_seq_tuple (seqrel, & buf , &seqdatatuple);
554 RelationSetNewRelfilenumber (seqrel, newrelpersistence);
555 fill_seq_with_data (seqrel, &seqdatatuple);
559 }
561 void
563 {
564 Relation rel;
565 HeapTuple tuple;
567 rel = table_open (SequenceRelationId, RowExclusiveLock );
570 if (! HeapTupleIsValid (tuple))
571 elog ( ERROR , "cache lookup failed for sequence %u" , relid);
573 CatalogTupleDelete (rel, &tuple-> t_self );
575 ReleaseSysCache (tuple);
577 }
579 /*
580 * Note: nextval with a text argument is no longer exported as a pg_proc
581 * entry, but we keep it around to ease porting of C code that may have
582 * called the function directly.
583 */
586 {
588 RangeVar *sequence;
589 Oid relid;
593 /*
594 * XXX: This is not safe in the presence of concurrent DDL, but acquiring
595 * a lock here is more expensive than letting nextval_internal do it,
596 * since the latter maintains a cache that keeps us from hitting the lock
597 * manager more than once per transaction. It's not clear whether the
598 * performance penalty is material in practice, but for now, we do it this
599 * way.
600 */
601 relid = RangeVarGetRelid (sequence, NoLock , false );
604 }
608 {
609 Oid relid = PG_GETARG_OID (0);
612 }
614 int64
615 nextval_internal ( Oid relid, bool check_permissions)
616 {
617 SeqTable elm;
618 Relation seqrel;
620 Page page;
621 HeapTuple pgstuple;
623 HeapTupleData seqdatatuple;
625 int64 incby,
626 maxv,
627 minv,
628 cache,
629 log,
630 fetch,
631 last;
632 int64 result,
633 next ,
634 rescnt = 0;
635 bool cycle;
636 bool logit = false ;
638 /* open and lock sequence */
639 init_sequence (relid, &elm, &seqrel);
641 if (check_permissions &&
645 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
646 errmsg ( "permission denied for sequence %s" ,
649 /* read-only transactions may only modify temp sequences */
650 if (!seqrel-> rd_islocaltemp )
651 PreventCommandIfReadOnly ( "nextval()" );
653 /*
654 * Forbid this during parallel operation because, to make it work, the
655 * cooperating backends would need to share the backend-local cached
656 * sequence information. Currently, we don't support that.
657 */
660 if (elm-> last != elm-> cached ) /* some numbers were cached */
661 {
662 Assert (elm-> last_valid );
663 Assert (elm-> increment != 0);
664 elm-> last += elm-> increment ;
667 return elm-> last ;
668 }
671 if (! HeapTupleIsValid (pgstuple))
672 elog ( ERROR , "cache lookup failed for sequence %u" , relid);
673 pgsform = ( Form_pg_sequence ) GETSTRUCT (pgstuple);
674 incby = pgsform->seqincrement;
675 maxv = pgsform->seqmax;
676 minv = pgsform->seqmin;
677 cache = pgsform->seqcache;
678 cycle = pgsform->seqcycle;
679 ReleaseSysCache (pgstuple);
681 /* lock page' buffer and read tuple */
682 seq = read_seq_tuple (seqrel, & buf , &seqdatatuple);
683 page = BufferGetPage ( buf );
685 elm-> increment = incby;
686 last = next = result = seq-> last_value ;
687 fetch = cache;
688 log = seq-> log_cnt ;
690 if (!seq-> is_called )
691 {
692 rescnt++; /* return last_value if not is_called */
693 fetch--;
694 }
696 /*
697 * Decide whether we should emit a WAL log record. If so, force up the
698 * fetch count to grab SEQ_LOG_VALS more values than we actually need to
699 * cache. (These will then be usable without logging.)
700 *
701 * If this is the first nextval after a checkpoint, we must force a new
702 * WAL record to be written anyway, else replay starting from the
703 * checkpoint would fail to advance the sequence past the logged values.
704 * In this case we may as well fetch extra values.
705 */
706 if (log < fetch || !seq->is_called)
707 {
708 /* forced log to satisfy local demand for values */
709 fetch = log = fetch + SEQ_LOG_VALS ;
710 logit = true ;
711 }
712 else
713 {
716 if ( PageGetLSN (page) <= redoptr)
717 {
718 /* last update of seq was before checkpoint */
719 fetch = log = fetch + SEQ_LOG_VALS ;
720 logit = true ;
721 }
722 }
724 while (fetch) /* try to fetch cache [+ log ] numbers */
725 {
726 /*
727 * Check MAXVALUE for ascending sequences and MINVALUE for descending
728 * sequences
729 */
730 if (incby > 0)
731 {
732 /* ascending sequence */
733 if ((maxv >= 0 && next > maxv - incby) ||
734 (maxv < 0 && next + incby > maxv))
735 {
736 if (rescnt > 0)
737 break ; /* stop fetching */
738 if (!cycle)
740 ( errcode (ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
741 errmsg ( "nextval: reached maximum value of sequence \"%s\" (%lld)" ,
743 ( long long ) maxv)));
744 next = minv;
745 }
746 else
747 next += incby;
748 }
749 else
750 {
751 /* descending sequence */
752 if ((minv < 0 && next < minv - incby) ||
753 (minv >= 0 && next + incby < minv))
754 {
755 if (rescnt > 0)
756 break ; /* stop fetching */
757 if (!cycle)
759 ( errcode (ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
760 errmsg ( "nextval: reached minimum value of sequence \"%s\" (%lld)" ,
762 ( long long ) minv)));
763 next = maxv;
764 }
765 else
766 next += incby;
767 }
768 fetch--;
769 if (rescnt < cache)
770 {
771 log--;
772 rescnt++;
773 last = next ;
774 if (rescnt == 1) /* if it's first result - */
775 result = next ; /* it's what to return */
776 }
777 }
779 log -= fetch; /* adjust for any unfetched numbers */
780 Assert (log >= 0);
782 /* save info in local cache */
783 elm-> last = result; /* last returned number */
784 elm-> cached = last; /* last fetched number */
785 elm-> last_valid = true ;
789 /*
790 * If something needs to be WAL logged, acquire an xid, so this
791 * transaction's commit will trigger a WAL flush and wait for syncrep.
792 * It's sufficient to ensure the toplevel transaction has an xid, no need
793 * to assign xids subxacts, that'll already trigger an appropriate wait.
794 * (Have to do that here, so we're outside the critical section)
795 */
796 if (logit && RelationNeedsWAL (seqrel))
799 /* ready to change the on-disk (or really, in-buffer) tuple */
802 /*
803 * We must mark the buffer dirty before doing XLogInsert(); see notes in
804 * SyncOneBuffer(). However, we don't apply the desired changes just yet.
805 * This looks like a violation of the buffer update protocol, but it is in
806 * fact safe because we hold exclusive lock on the buffer. Any other
807 * process, including a checkpoint, that tries to examine the buffer
808 * contents will block until we release the lock, and then will see the
809 * final state that we install below.
810 */
813 /* XLOG stuff */
814 if (logit && RelationNeedsWAL (seqrel))
815 {
816 xl_seq_rec xlrec;
817 XLogRecPtr recptr;
819 /*
820 * We don't log the current state of the tuple, but rather the state
821 * as it would appear after "log" more fetches. This lets us skip
822 * that many future WAL records, at the cost that we lose those
823 * sequence values if we crash.
824 */
828 /* set values that will be saved in xlog */
830 seq-> is_called = true ;
831 seq-> log_cnt = 0;
833 xlrec. locator = seqrel-> rd_locator ;
835 XLogRegisterData (( char *) &xlrec, sizeof ( xl_seq_rec ));
836 XLogRegisterData (( char *) seqdatatuple. t_data , seqdatatuple. t_len );
838 recptr = XLogInsert (RM_SEQ_ID, XLOG_SEQ_LOG );
840 PageSetLSN (page, recptr);
841 }
843 /* Now update sequence tuple to the intended final state */
844 seq-> last_value = last; /* last fetched number */
845 seq-> is_called = true ;
846 seq-> log_cnt = log; /* how much is logged */
854 return result;
855 }
859 {
860 Oid relid = PG_GETARG_OID (0);
861 int64 result;
862 SeqTable elm;
863 Relation seqrel;
865 /* open and lock sequence */
866 init_sequence (relid, &elm, &seqrel);
871 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
872 errmsg ( "permission denied for sequence %s" ,
875 if (!elm-> last_valid )
877 ( errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
878 errmsg ( "currval of sequence \"%s\" is not yet defined in this session" ,
881 result = elm-> last ;
885 PG_RETURN_INT64 (result);
886 }
890 {
891 Relation seqrel;
892 int64 result;
894 if ( last_used_seq == NULL)
896 ( errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
897 errmsg ( "lastval is not yet defined in this session" )));
899 /* Someone may have dropped the sequence since the last nextval() */
902 ( errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
903 errmsg ( "lastval is not yet defined in this session" )));
907 /* nextval() must have already been called for this sequence */
913 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
914 errmsg ( "permission denied for sequence %s" ,
917 result = last_used_seq -> last ;
920 PG_RETURN_INT64 (result);
921 }
923 /*
924 * Main internal procedure that handles 2 & 3 arg forms of SETVAL.
925 *
926 * Note that the 3 arg version (which sets the is_called flag) is
927 * only for use in pg_dump, and setting the is_called flag may not
928 * work if multiple users are attached to the database and referencing
929 * the sequence (unlikely if pg_dump is restoring it).
930 *
931 * It is necessary to have the 3 arg version so that pg_dump can
932 * restore the state of a sequence exactly during data-only restores -
933 * it is the only way to clear the is_called flag in an existing
934 * sequence.
935 */
936 static void
937 do_setval ( Oid relid, int64 next , bool iscalled)
938 {
939 SeqTable elm;
940 Relation seqrel;
942 HeapTupleData seqdatatuple;
944 HeapTuple pgstuple;
946 int64 maxv,
947 minv;
949 /* open and lock sequence */
950 init_sequence (relid, &elm, &seqrel);
954 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
955 errmsg ( "permission denied for sequence %s" ,
959 if (! HeapTupleIsValid (pgstuple))
960 elog ( ERROR , "cache lookup failed for sequence %u" , relid);
961 pgsform = ( Form_pg_sequence ) GETSTRUCT (pgstuple);
962 maxv = pgsform->seqmax;
963 minv = pgsform->seqmin;
964 ReleaseSysCache (pgstuple);
966 /* read-only transactions may only modify temp sequences */
967 if (!seqrel-> rd_islocaltemp )
968 PreventCommandIfReadOnly ( "setval()" );
970 /*
971 * Forbid this during parallel operation because, to make it work, the
972 * cooperating backends would need to share the backend-local cached
973 * sequence information. Currently, we don't support that.
974 */
977 /* lock page' buffer and read tuple */
978 seq = read_seq_tuple (seqrel, & buf , &seqdatatuple);
980 if (( next < minv) || ( next > maxv))
982 ( errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
983 errmsg ( "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" ,
984 ( long long ) next , RelationGetRelationName (seqrel),
985 ( long long ) minv, ( long long ) maxv)));
987 /* Set the currval() state only if iscalled = true */
988 if (iscalled)
989 {
990 elm-> last = next ; /* last returned number */
991 elm-> last_valid = true ;
992 }
994 /* In any case, forget any future cached numbers */
995 elm-> cached = elm-> last ;
997 /* check the comment above nextval_internal()'s equivalent call. */
998 if ( RelationNeedsWAL (seqrel))
1001 /* ready to change the on-disk (or really, in-buffer) tuple */
1004 seq-> last_value = next ; /* last fetched number */
1005 seq-> is_called = iscalled;
1006 seq-> log_cnt = 0;
1010 /* XLOG stuff */
1011 if ( RelationNeedsWAL (seqrel))
1012 {
1013 xl_seq_rec xlrec;
1014 XLogRecPtr recptr;
1020 xlrec. locator = seqrel-> rd_locator ;
1021 XLogRegisterData (( char *) &xlrec, sizeof ( xl_seq_rec ));
1022 XLogRegisterData (( char *) seqdatatuple. t_data , seqdatatuple. t_len );
1024 recptr = XLogInsert (RM_SEQ_ID, XLOG_SEQ_LOG );
1026 PageSetLSN (page, recptr);
1027 }
1034 }
1036 /*
1037 * Implement the 2 arg setval procedure.
1038 * See do_setval for discussion.
1039 */
1042 {
1043 Oid relid = PG_GETARG_OID (0);
1044 int64 next = PG_GETARG_INT64 (1);
1046 do_setval (relid, next , true );
1049 }
1051 /*
1052 * Implement the 3 arg setval procedure.
1053 * See do_setval for discussion.
1054 */
1057 {
1058 Oid relid = PG_GETARG_OID (0);
1059 int64 next = PG_GETARG_INT64 (1);
1060 bool iscalled = PG_GETARG_BOOL (2);
1062 do_setval (relid, next , iscalled);
1065 }
1068 /*
1069 * Open the sequence and acquire lock if needed
1070 *
1071 * If we haven't touched the sequence already in this transaction,
1072 * we need to acquire a lock. We arrange for the lock to
1073 * be owned by the top transaction, so that we don't need to do it
1074 * more than once per xact.
1075 */
1076 static Relation
1078 {
1081 /* Get the lock if not already held in this xact */
1082 if (seq-> lxid != thislxid)
1083 {
1084 ResourceOwner currentOwner;
1086 currentOwner = CurrentResourceOwner ;
1091 CurrentResourceOwner = currentOwner;
1093 /* Flag that we have a lock in the current xact */
1094 seq-> lxid = thislxid;
1095 }
1097 /* We now know we have the lock, and can safely open the rel */
1098 return relation_open (seq-> relid , NoLock );
1099 }
1101 /*
1102 * Creates the hash table for storing sequence data
1103 */
1104 static void
1105 create_seq_hashtable ( void )
1106 {
1107 HASHCTL ctl;
1109 ctl. keysize = sizeof ( Oid );
1110 ctl. entrysize = sizeof ( SeqTableData );
1112 seqhashtab = hash_create ( "Sequence values" , 16, &ctl,
1114 }
1116 /*
1117 * Given a relation OID, open and lock the sequence. p_elm and p_rel are
1118 * output parameters.
1119 */
1120 static void
1122 {
1123 SeqTable elm;
1124 Relation seqrel;
1125 bool found;
1127 /* Find or create a hash table entry for this sequence */
1128 if ( seqhashtab == NULL)
1131 elm = ( SeqTable ) hash_search ( seqhashtab , &relid, HASH_ENTER , &found);
1133 /*
1134 * Initialize the new hash table entry if it did not exist already.
1135 *
1136 * NOTE: seqhashtab entries are stored for the life of a backend (unless
1137 * explicitly discarded with DISCARD). If the sequence itself is deleted
1138 * then the entry becomes wasted memory, but it's small enough that this
1139 * should not matter.
1140 */
1141 if (!found)
1142 {
1143 /* relid already filled in */
1146 elm-> last_valid = false ;
1147 elm-> last = elm-> cached = 0;
1148 }
1150 /*
1151 * Open the sequence relation.
1152 */
1153 seqrel = lock_and_open_sequence (elm);
1155 if (seqrel-> rd_rel ->relkind != RELKIND_SEQUENCE)
1157 ( errcode (ERRCODE_WRONG_OBJECT_TYPE),
1158 errmsg ( "\"%s\" is not a sequence" ,
1161 /*
1162 * If the sequence has been transactionally replaced since we last saw it,
1163 * discard any cached-but-unissued values. We do not touch the currval()
1164 * state, however.
1165 */
1166 if (seqrel-> rd_rel ->relfilenode != elm-> filenumber )
1167 {
1168 elm-> filenumber = seqrel-> rd_rel ->relfilenode;
1169 elm-> cached = elm-> last ;
1170 }
1172 /* Return results */
1173 *p_elm = elm;
1174 *p_rel = seqrel;
1175 }
1178 /*
1179 * Given an opened sequence relation, lock the page buffer and find the tuple
1180 *
1181 * *buf receives the reference to the pinned-and-ex-locked buffer
1182 * *seqdatatuple receives the reference to the sequence tuple proper
1183 * (this arg should point to a local variable of type HeapTupleData)
1184 *
1185 * Function's return value points to the data payload of the tuple
1186 */
1189 {
1190 Page page;
1191 ItemId lp;
1193 Form_pg_sequence_data seq;
1195 * buf = ReadBuffer (rel, 0);
1198 page = BufferGetPage (* buf );
1201 if (sm-> magic != SEQ_MAGIC )
1202 elog ( ERROR , "bad magic number in sequence \"%s\": %08X" ,
1208 /* Note we currently only bother to set these two fields of *seqdatatuple */
1209 seqdatatuple-> t_data = ( HeapTupleHeader ) PageGetItem (page, lp);
1210 seqdatatuple-> t_len = ItemIdGetLength (lp);
1212 /*
1213 * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1214 * a sequence, which would leave a non-frozen XID in the sequence tuple's
1215 * xmax, which eventually leads to clog access failures or worse. If we
1216 * see this has happened, clean up after it. We treat this like a hint
1217 * bit update, ie, don't bother to WAL-log it, since we can certainly do
1218 * this again if the update gets lost.
1219 */
1222 {
1227 }
1229 seq = ( Form_pg_sequence_data ) GETSTRUCT (seqdatatuple);
1231 return seq;
1232 }
1234 /*
1235 * init_params: process the options list of CREATE or ALTER SEQUENCE, and
1236 * store the values into appropriate fields of seqform, for changes that go
1237 * into the pg_sequence catalog, and fields of seqdataform for changes to the
1238 * sequence relation itself. Set *need_seq_rewrite to true if we changed any
1239 * parameters that require rewriting the sequence's relation (interesting for
1240 * ALTER SEQUENCE). Also set *owned_by to any OWNED BY option, or to NIL if
1241 * there is none.
1242 *
1243 * If isInit is true, fill any unspecified options with default values;
1244 * otherwise, do not change existing options that aren't explicitly overridden.
1245 *
1246 * Note: we force a sequence rewrite whenever we change parameters that affect
1247 * generation of future sequence values, even if the seqdataform per se is not
1248 * changed. This allows ALTER SEQUENCE to behave transactionally. Currently,
1249 * the only option that doesn't cause that is OWNED BY. It's *necessary* for
1250 * ALTER SEQUENCE OWNED BY to not rewrite the sequence, because that would
1251 * break pg_upgrade by causing unwanted changes in the sequence's
1252 * relfilenumber.
1253 */
1254 static void
1256 bool isInit,
1257 Form_pg_sequence seqform,
1258 Form_pg_sequence_data seqdataform,
1259 bool *need_seq_rewrite,
1260 List **owned_by)
1261 {
1262 DefElem *as_type = NULL;
1263 DefElem *start_value = NULL;
1264 DefElem *restart_value = NULL;
1265 DefElem *increment_by = NULL;
1266 DefElem *max_value = NULL;
1267 DefElem *min_value = NULL;
1268 DefElem *cache_value = NULL;
1269 DefElem *is_cycled = NULL;
1270 ListCell * option ;
1271 bool reset_max_value = false ;
1272 bool reset_min_value = false ;
1274 *need_seq_rewrite = false ;
1275 *owned_by = NIL ;
1277 foreach ( option , options )
1278 {
1281 if (strcmp(defel-> defname , "as" ) == 0)
1282 {
1283 if (as_type)
1284 errorConflictingDefElem (defel, pstate);
1285 as_type = defel;
1286 *need_seq_rewrite = true ;
1287 }
1288 else if (strcmp(defel-> defname , "increment" ) == 0)
1289 {
1290 if (increment_by)
1291 errorConflictingDefElem (defel, pstate);
1292 increment_by = defel;
1293 *need_seq_rewrite = true ;
1294 }
1295 else if (strcmp(defel-> defname , "start" ) == 0)
1296 {
1297 if (start_value)
1298 errorConflictingDefElem (defel, pstate);
1299 start_value = defel;
1300 *need_seq_rewrite = true ;
1301 }
1302 else if (strcmp(defel-> defname , "restart" ) == 0)
1303 {
1304 if (restart_value)
1305 errorConflictingDefElem (defel, pstate);
1306 restart_value = defel;
1307 *need_seq_rewrite = true ;
1308 }
1309 else if (strcmp(defel-> defname , "maxvalue" ) == 0)
1310 {
1311 if (max_value)
1312 errorConflictingDefElem (defel, pstate);
1313 max_value = defel;
1314 *need_seq_rewrite = true ;
1315 }
1316 else if (strcmp(defel-> defname , "minvalue" ) == 0)
1317 {
1318 if (min_value)
1319 errorConflictingDefElem (defel, pstate);
1320 min_value = defel;
1321 *need_seq_rewrite = true ;
1322 }
1323 else if (strcmp(defel-> defname , "cache" ) == 0)
1324 {
1325 if (cache_value)
1326 errorConflictingDefElem (defel, pstate);
1327 cache_value = defel;
1328 *need_seq_rewrite = true ;
1329 }
1330 else if (strcmp(defel-> defname , "cycle" ) == 0)
1331 {
1332 if (is_cycled)
1333 errorConflictingDefElem (defel, pstate);
1334 is_cycled = defel;
1335 *need_seq_rewrite = true ;
1336 }
1337 else if (strcmp(defel-> defname , "owned_by" ) == 0)
1338 {
1339 if (*owned_by)
1340 errorConflictingDefElem (defel, pstate);
1341 *owned_by = defGetQualifiedName (defel);
1342 }
1343 else if (strcmp(defel-> defname , "sequence_name" ) == 0)
1344 {
1345 /*
1346 * The parser allows this, but it is only for identity columns, in
1347 * which case it is filtered out in parse_utilcmd.c. We only get
1348 * here if someone puts it into a CREATE SEQUENCE.
1349 */
1351 ( errcode (ERRCODE_SYNTAX_ERROR),
1352 errmsg ( "invalid sequence option SEQUENCE NAME" ),
1353 parser_errposition (pstate, defel-> location )));
1354 }
1355 else
1356 elog ( ERROR , "option \"%s\" not recognized" ,
1357 defel-> defname );
1358 }
1360 /*
1361 * We must reset log_cnt when isInit or when changing any parameters that
1362 * would affect future nextval allocations.
1363 */
1364 if (isInit)
1365 seqdataform-> log_cnt = 0;
1367 /* AS type */
1368 if (as_type != NULL)
1369 {
1370 Oid newtypid = typenameTypeId (pstate, defGetTypeName (as_type));
1372 if (newtypid != INT2OID &&
1373 newtypid != INT4OID &&
1374 newtypid != INT8OID)
1376 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1377 for_identity
1378 ? errmsg ( "identity column type must be smallint, integer, or bigint" )
1379 : errmsg ( "sequence type must be smallint, integer, or bigint" )));
1381 if (!isInit)
1382 {
1383 /*
1384 * When changing type and the old sequence min/max values were the
1385 * min/max of the old type, adjust sequence min/max values to
1386 * min/max of new type. (Otherwise, the user chose explicit
1387 * min/max values, which we'll leave alone.)
1388 */
1389 if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX ) ||
1390 (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX ) ||
1391 (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX ))
1392 reset_max_value = true ;
1393 if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN ) ||
1394 (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN ) ||
1395 (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN ))
1396 reset_min_value = true ;
1397 }
1399 seqform->seqtypid = newtypid;
1400 }
1401 else if (isInit)
1402 {
1403 seqform->seqtypid = INT8OID;
1404 }
1406 /* INCREMENT BY */
1407 if (increment_by != NULL)
1408 {
1409 seqform->seqincrement = defGetInt64 (increment_by);
1410 if (seqform->seqincrement == 0)
1412 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1413 errmsg ( "INCREMENT must not be zero" )));
1414 seqdataform-> log_cnt = 0;
1415 }
1416 else if (isInit)
1417 {
1418 seqform->seqincrement = 1;
1419 }
1421 /* CYCLE */
1422 if (is_cycled != NULL)
1423 {
1424 seqform->seqcycle = boolVal (is_cycled-> arg );
1425 Assert ( BoolIsValid (seqform->seqcycle));
1426 seqdataform-> log_cnt = 0;
1427 }
1428 else if (isInit)
1429 {
1430 seqform->seqcycle = false ;
1431 }
1433 /* MAXVALUE (null arg means NO MAXVALUE) */
1434 if (max_value != NULL && max_value-> arg )
1435 {
1436 seqform->seqmax = defGetInt64 (max_value);
1437 seqdataform-> log_cnt = 0;
1438 }
1439 else if (isInit || max_value != NULL || reset_max_value)
1440 {
1441 if (seqform->seqincrement > 0 || reset_max_value)
1442 {
1443 /* ascending seq */
1444 if (seqform->seqtypid == INT2OID)
1445 seqform->seqmax = PG_INT16_MAX ;
1446 else if (seqform->seqtypid == INT4OID)
1447 seqform->seqmax = PG_INT32_MAX ;
1448 else
1449 seqform->seqmax = PG_INT64_MAX ;
1450 }
1451 else
1452 seqform->seqmax = -1; /* descending seq */
1453 seqdataform-> log_cnt = 0;
1454 }
1456 /* Validate maximum value. No need to check INT8 as seqmax is an int64 */
1457 if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX ))
1458 || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX )))
1460 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1461 errmsg ( "MAXVALUE (%lld) is out of range for sequence data type %s" ,
1462 ( long long ) seqform->seqmax,
1463 format_type_be (seqform->seqtypid))));
1465 /* MINVALUE (null arg means NO MINVALUE) */
1466 if (min_value != NULL && min_value-> arg )
1467 {
1468 seqform->seqmin = defGetInt64 (min_value);
1469 seqdataform-> log_cnt = 0;
1470 }
1471 else if (isInit || min_value != NULL || reset_min_value)
1472 {
1473 if (seqform->seqincrement < 0 || reset_min_value)
1474 {
1475 /* descending seq */
1476 if (seqform->seqtypid == INT2OID)
1477 seqform->seqmin = PG_INT16_MIN ;
1478 else if (seqform->seqtypid == INT4OID)
1479 seqform->seqmin = PG_INT32_MIN ;
1480 else
1481 seqform->seqmin = PG_INT64_MIN ;
1482 }
1483 else
1484 seqform->seqmin = 1; /* ascending seq */
1485 seqdataform-> log_cnt = 0;
1486 }
1488 /* Validate minimum value. No need to check INT8 as seqmin is an int64 */
1489 if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX ))
1490 || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX )))
1492 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1493 errmsg ( "MINVALUE (%lld) is out of range for sequence data type %s" ,
1494 ( long long ) seqform->seqmin,
1495 format_type_be (seqform->seqtypid))));
1497 /* crosscheck min/max */
1498 if (seqform->seqmin >= seqform->seqmax)
1500 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1501 errmsg ( "MINVALUE (%lld) must be less than MAXVALUE (%lld)" ,
1502 ( long long ) seqform->seqmin,
1503 ( long long ) seqform->seqmax)));
1505 /* START WITH */
1506 if (start_value != NULL)
1507 {
1508 seqform->seqstart = defGetInt64 (start_value);
1509 }
1510 else if (isInit)
1511 {
1512 if (seqform->seqincrement > 0)
1513 seqform->seqstart = seqform->seqmin; /* ascending seq */
1514 else
1515 seqform->seqstart = seqform->seqmax; /* descending seq */
1516 }
1518 /* crosscheck START */
1519 if (seqform->seqstart < seqform->seqmin)
1521 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1522 errmsg ( "START value (%lld) cannot be less than MINVALUE (%lld)" ,
1523 ( long long ) seqform->seqstart,
1524 ( long long ) seqform->seqmin)));
1525 if (seqform->seqstart > seqform->seqmax)
1527 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1528 errmsg ( "START value (%lld) cannot be greater than MAXVALUE (%lld)" ,
1529 ( long long ) seqform->seqstart,
1530 ( long long ) seqform->seqmax)));
1532 /* RESTART [WITH] */
1533 if (restart_value != NULL)
1534 {
1535 if (restart_value-> arg != NULL)
1536 seqdataform-> last_value = defGetInt64 (restart_value);
1537 else
1538 seqdataform-> last_value = seqform->seqstart;
1539 seqdataform-> is_called = false ;
1540 seqdataform-> log_cnt = 0;
1541 }
1542 else if (isInit)
1543 {
1544 seqdataform-> last_value = seqform->seqstart;
1545 seqdataform-> is_called = false ;
1546 }
1548 /* crosscheck RESTART (or current value, if changing MIN/MAX) */
1549 if (seqdataform-> last_value < seqform->seqmin)
1551 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1552 errmsg ( "RESTART value (%lld) cannot be less than MINVALUE (%lld)" ,
1553 ( long long ) seqdataform-> last_value ,
1554 ( long long ) seqform->seqmin)));
1555 if (seqdataform-> last_value > seqform->seqmax)
1557 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1558 errmsg ( "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" ,
1559 ( long long ) seqdataform-> last_value ,
1560 ( long long ) seqform->seqmax)));
1562 /* CACHE */
1563 if (cache_value != NULL)
1564 {
1565 seqform->seqcache = defGetInt64 (cache_value);
1566 if (seqform->seqcache <= 0)
1568 ( errcode (ERRCODE_INVALID_PARAMETER_VALUE),
1569 errmsg ( "CACHE (%lld) must be greater than zero" ,
1570 ( long long ) seqform->seqcache)));
1571 seqdataform-> log_cnt = 0;
1572 }
1573 else if (isInit)
1574 {
1575 seqform->seqcache = 1;
1576 }
1577 }
1579 /*
1580 * Process an OWNED BY option for CREATE/ALTER SEQUENCE
1581 *
1582 * Ownership permissions on the sequence are already checked,
1583 * but if we are establishing a new owned-by dependency, we must
1584 * enforce that the referenced table has the same owner and namespace
1585 * as the sequence.
1586 */
1587 static void
1588 process_owned_by ( Relation seqrel, List *owned_by, bool for_identity)
1589 {
1590 DependencyType deptype;
1591 int nnames;
1592 Relation tablerel;
1595 deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO ;
1597 nnames = list_length (owned_by);
1598 Assert (nnames > 0);
1599 if (nnames == 1)
1600 {
1601 /* Must be OWNED BY NONE */
1602 if (strcmp( strVal ( linitial (owned_by)), "none" ) != 0)
1604 ( errcode (ERRCODE_SYNTAX_ERROR),
1605 errmsg ( "invalid OWNED BY option" ),
1606 errhint ( "Specify OWNED BY table.column or OWNED BY NONE." )));
1607 tablerel = NULL;
1608 attnum = 0;
1609 }
1610 else
1611 {
1613 char *attrname;
1614 RangeVar *rel;
1616 /* Separate relname and attr name */
1617 relname = list_copy_head (owned_by, nnames - 1);
1618 attrname = strVal ( llast (owned_by));
1620 /* Open and lock rel to ensure it won't go away meanwhile */
1624 /* Must be a regular or foreign table */
1625 if (!(tablerel-> rd_rel ->relkind == RELKIND_RELATION ||
1626 tablerel-> rd_rel ->relkind == RELKIND_FOREIGN_TABLE ||
1627 tablerel-> rd_rel ->relkind == RELKIND_VIEW ||
1628 tablerel-> rd_rel ->relkind == RELKIND_PARTITIONED_TABLE))
1630 ( errcode (ERRCODE_WRONG_OBJECT_TYPE),
1631 errmsg ( "sequence cannot be owned by relation \"%s\"" ,
1633 errdetail_relkind_not_supported (tablerel-> rd_rel ->relkind)));
1635 /* We insist on same owner and schema */
1636 if (seqrel-> rd_rel ->relowner != tablerel-> rd_rel ->relowner)
1638 ( errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1639 errmsg ( "sequence must have same owner as table it is linked to" )));
1640 if ( RelationGetNamespace (seqrel) != RelationGetNamespace (tablerel))
1642 ( errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1643 errmsg ( "sequence must be in same schema as table it is linked to" )));
1645 /* Now, fetch the attribute number from the system cache */
1646 attnum = get_attnum ( RelationGetRelid (tablerel), attrname);
1649 ( errcode (ERRCODE_UNDEFINED_COLUMN),
1650 errmsg ( "column \"%s\" of relation \"%s\" does not exist" ,
1651 attrname, RelationGetRelationName (tablerel))));
1652 }
1654 /*
1655 * Catch user explicitly running OWNED BY on identity sequence.
1656 */
1657 if (deptype == DEPENDENCY_AUTO )
1658 {
1659 Oid tableId;
1660 int32 colId;
1662 if ( sequenceIsOwned ( RelationGetRelid (seqrel), DEPENDENCY_INTERNAL , &tableId, &colId))
1664 ( errcode (ERRCODE_FEATURE_NOT_SUPPORTED),
1665 errmsg ( "cannot change ownership of identity sequence" ),
1666 errdetail ( "Sequence \"%s\" is linked to table \"%s\"." ,
1668 get_rel_name (tableId))));
1669 }
1671 /*
1672 * OK, we are ready to update pg_depend. First remove any existing
1673 * dependencies for the sequence, then optionally add a new one.
1674 */
1676 RelationRelationId, deptype);
1678 if (tablerel)
1679 {
1680 ObjectAddress refobject,
1681 depobject;
1683 refobject. classId = RelationRelationId;
1684 refobject. objectId = RelationGetRelid (tablerel);
1685 refobject. objectSubId = attnum ;
1686 depobject. classId = RelationRelationId;
1687 depobject. objectId = RelationGetRelid (seqrel);
1688 depobject. objectSubId = 0;
1689 recordDependencyOn (&depobject, &refobject, deptype);
1690 }
1692 /* Done, but hold lock until commit */
1693 if (tablerel)
1694 relation_close (tablerel, NoLock );
1695 }
1698 /*
1699 * Return sequence parameters in a list of the form created by the parser.
1700 */
1701 List *
1703 {
1704 HeapTuple pgstuple;
1705 Form_pg_sequence pgsform;
1709 if (! HeapTupleIsValid (pgstuple))
1710 elog ( ERROR , "cache lookup failed for sequence %u" , relid);
1711 pgsform = ( Form_pg_sequence ) GETSTRUCT (pgstuple);
1713 /* Use makeFloat() for 64-bit integers, like gram.y does. */
1715 makeDefElem ( "cache" , ( Node *) makeFloat ( psprintf ( INT64_FORMAT , pgsform->seqcache)), -1));
1717 makeDefElem ( "cycle" , ( Node *) makeBoolean (pgsform->seqcycle), -1));
1719 makeDefElem ( "increment" , ( Node *) makeFloat ( psprintf ( INT64_FORMAT , pgsform->seqincrement)), -1));
1721 makeDefElem ( "maxvalue" , ( Node *) makeFloat ( psprintf ( INT64_FORMAT , pgsform->seqmax)), -1));
1723 makeDefElem ( "minvalue" , ( Node *) makeFloat ( psprintf ( INT64_FORMAT , pgsform->seqmin)), -1));
1725 makeDefElem ( "start" , ( Node *) makeFloat ( psprintf ( INT64_FORMAT , pgsform->seqstart)), -1));
1727 ReleaseSysCache (pgstuple);
1729 return options ;
1730 }
1732 /*
1733 * Return sequence parameters (formerly for use by information schema)
1734 */
1737 {
1738 Oid relid = PG_GETARG_OID (0);
1739 TupleDesc tupdesc;
1741 bool isnull[7];
1742 HeapTuple pgstuple;
1743 Form_pg_sequence pgsform;
1747 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
1748 errmsg ( "permission denied for sequence %s" ,
1749 get_rel_name (relid))));
1751 if ( get_call_result_type (fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE )
1752 elog ( ERROR , "return type must be a row type" );
1754 memset(isnull, 0, sizeof (isnull));
1757 if (! HeapTupleIsValid (pgstuple))
1758 elog ( ERROR , "cache lookup failed for sequence %u" , relid);
1759 pgsform = ( Form_pg_sequence ) GETSTRUCT (pgstuple);
1761 values [0] = Int64GetDatum (pgsform->seqstart);
1762 values [1] = Int64GetDatum (pgsform->seqmin);
1763 values [2] = Int64GetDatum (pgsform->seqmax);
1764 values [3] = Int64GetDatum (pgsform->seqincrement);
1765 values [4] = BoolGetDatum (pgsform->seqcycle);
1766 values [5] = Int64GetDatum (pgsform->seqcache);
1767 values [6] = ObjectIdGetDatum (pgsform->seqtypid);
1769 ReleaseSysCache (pgstuple);
1771 return HeapTupleGetDatum ( heap_form_tuple (tupdesc, values , isnull));
1772 }
1774 /*
1775 * Return the last value from the sequence
1776 *
1777 * Note: This has a completely different meaning than lastval().
1778 */
1781 {
1782 Oid relid = PG_GETARG_OID (0);
1783 SeqTable elm;
1784 Relation seqrel;
1786 HeapTupleData seqtuple;
1788 bool is_called;
1789 int64 result;
1791 /* open and lock sequence */
1792 init_sequence (relid, &elm, &seqrel);
1796 ( errcode (ERRCODE_INSUFFICIENT_PRIVILEGE),
1797 errmsg ( "permission denied for sequence %s" ,
1800 seq = read_seq_tuple (seqrel, & buf , &seqtuple);
1802 is_called = seq-> is_called ;
1803 result = seq-> last_value ;
1808 if (is_called)
1809 PG_RETURN_INT64 (result);
1810 else
1812 }
1815 void
1817 {
1818 XLogRecPtr lsn = record-> EndRecPtr ;
1820 Buffer buffer;
1821 Page page;
1822 Page localpage;
1823 char *item;
1824 Size itemsz;
1828 if (info != XLOG_SEQ_LOG )
1829 elog ( PANIC , "seq_redo: unknown op code %u" , info);
1831 buffer = XLogInitBufferForRedo (record, 0);
1832 page = ( Page ) BufferGetPage (buffer);
1834 /*
1835 * We always reinit the page. However, since this WAL record type is also
1836 * used for updating sequences, it's possible that a hot-standby backend
1837 * is examining the page concurrently; so we mustn't transiently trash the
1838 * buffer. The solution is to build the correct new page contents in
1839 * local workspace and then memcpy into the buffer. Then only bytes that
1840 * are supposed to change will change, even transiently. We must palloc
1841 * the local page for alignment reasons.
1842 */
1843 localpage = ( Page ) palloc ( BufferGetPageSize (buffer));
1845 PageInit (localpage, BufferGetPageSize (buffer), sizeof ( sequence_magic ));
1849 item = ( char *) xlrec + sizeof ( xl_seq_rec );
1850 itemsz = XLogRecGetDataLen (record) - sizeof ( xl_seq_rec );
1852 if ( PageAddItem (localpage, ( Item ) item, itemsz,
1854 elog ( PANIC , "seq_redo: failed to add item to page" );
1856 PageSetLSN (localpage, lsn);
1858 memcpy(page, localpage, BufferGetPageSize (buffer));
1859 MarkBufferDirty (buffer);
1862 pfree (localpage);
1863 }
1865 /*
1866 * Flush cached sequence information.
1867 */
1868 void
1870 {
1871 if ( seqhashtab )
1872 {
1874 seqhashtab = NULL;
1875 }
1877 last_used_seq = NULL;
1878 }
1880 /*
1881 * Mask a Sequence page before performing consistency checks on it.
1882 */
1883 void
1885 {
1889 }
@ ACLCHECK_OK
Definition: acl.h:182
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:3908
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
#define InvalidBackendId
Definition: backendid.h:23
uint32 BlockNumber
Definition: block.h:31
static int32 next
Definition: blutils.c:219
static Datum values[MAXATTR]
Definition: bootstrap.c:156
int Buffer
Definition: buf.h:23
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
void mask_unused_space(Page page)
Definition: bufmask.c:71
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3290
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:812
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4497
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2111
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4715
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:4544
void FlushRelationBuffers(Relation rel)
Definition: bufmgr.c:4058
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:708
BufferGetPage
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:355
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:341
@ EB_SKIP_EXTENSION_LOCK
Definition: bufmgr.h:73
@ EB_LOCK_FIRST
Definition: bufmgr.h:85
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:159
#define BMR_REL(p_rel)
Definition: bufmgr.h:106
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
Pointer Page
Definition: bufpage.h:78
static Item PageGetItem(Page page, ItemId itemId)
Definition: bufpage.h:351
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:240
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:388
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:383
static char * PageGetSpecialPointer(Page page)
Definition: bufpage.h:336
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:468
unsigned int uint32
Definition: c.h:495
#define PG_INT32_MAX
Definition: c.h:578
signed int int32
Definition: c.h:483
#define INT64_FORMAT
Definition: c.h:537
#define BoolIsValid(boolean)
Definition: c.h:746
#define FirstCommandId
Definition: c.h:657
#define PG_INT16_MIN
Definition: c.h:574
#define PG_INT64_MAX
Definition: c.h:581
#define PG_INT64_MIN
Definition: c.h:580
#define PG_INT32_MIN
Definition: c.h:577
uint32 LocalTransactionId
Definition: c.h:643
unsigned char uint8
Definition: c.h:493
#define PG_INT16_MAX
Definition: c.h:575
#define OidIsValid(objectId)
Definition: c.h:764
size_t Size
Definition: c.h:594
List * defGetQualifiedName(DefElem *def)
Definition: define.c:253
int64 defGetInt64(DefElem *def)
Definition: define.c:187
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:285
DependencyType
Definition: dependency.h:32
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:863
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1790
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_be(Oid type_oid)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:768
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1426
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define HeapTupleHeaderSetXminFrozen(tup)
#define HeapTupleHeaderSetXmin(tup, xid)
#define HeapTupleHeaderSetXmax(tup, xid)
#define HeapTupleHeaderSetCmin(tup, cid)
#define HEAP_XMAX_IS_MULTI
#define HEAP_XMAX_COMMITTED
#define GETSTRUCT(TUP)
#define HEAP_XMAX_INVALID
#define HeapTupleHeaderGetRawXmax(tup)
#define stmt
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
static struct @148 value
int i
Definition: isn.c:73
Pointer Item
Definition: item.h:17
ItemIdGetLength
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define ItemIdIsNormal(itemId)
Definition: itemid.h:99
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition: itemptr.h:135
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
List * list_copy_head(const List *oldlist, int len)
Definition: list.c:1592
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
#define InvalidLocalTransactionId
Definition: lock.h:65
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define ShareRowExclusiveLock
Definition: lockdefs.h:41
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:857
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1932
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:549
ColumnDef * makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
Definition: makefuncs.c:493
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
Oid GetUserId(void)
Definition: miscinit.c:509
#define InvalidMultiXactId
Definition: multixact.h:24
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:519
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3087
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:221
@ RVR_MISSING_OK
Definition: namespace.h:71
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
#define makeNode(_type_)
Definition: nodes.h:176
#define InvokeObjectPostAlterHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
#define InvalidOffsetNumber
Definition: off.h:26
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define ACL_USAGE
Definition: parsenodes.h:91
#define ACL_UPDATE
Definition: parsenodes.h:85
ACL_SELECT
#define ACL_SELECT
Definition: parsenodes.h:84
int16 attnum
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:257
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:350
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:827
#define lfirst(lc)
Definition: pg_list.h:172
#define llast(l)
Definition: pg_list.h:198
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
static char ** options
FormData_pg_sequence
Definition: pg_sequence.h:33
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:40
static char * buf
#define Int64GetDatumFast(X)
Definition: postgres.h:554
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define InvalidOid
unsigned int Oid
@ ONCOMMIT_NOOP
Definition: primnodes.h:49
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetDescr(relation)
Definition: rel.h:530
#define RelationGetRelationName(relation)
Definition: rel.h:538
#define RelationNeedsWAL(relation)
Definition: rel.h:629
#define RelationGetNamespace(relation)
Definition: rel.h:545
void RelationSetNewRelfilenumber(Relation relation, char persistence)
Definition: relcache.c:3710
Oid RelFileNumber
Definition: relpath.h:25
ForkNumber
Definition: relpath.h:48
@ MAIN_FORKNUM
Definition: relpath.h:50
@ INIT_FORKNUM
Definition: relpath.h:53
#define InvalidRelFileNumber
Definition: relpath.h:26
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:149
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
Definition: sequence.c:120
static void fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
Definition: sequence.c:358
void ResetSequence(Oid seq_relid)
Definition: sequence.c:261
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:337
struct sequence_magic sequence_magic
Datum setval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:1041
static SeqTableData * last_used_seq
Definition: sequence.c:96
ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
Definition: sequence.c:436
Datum pg_sequence_parameters(PG_FUNCTION_ARGS)
Definition: sequence.c:1736
Datum nextval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:607
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1121
#define SEQ_MAGIC
Definition: sequence.c:62
Datum setval3_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:1056
#define SEQ_LOG_VALS
Definition: sequence.c:57
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1188
Datum lastval(PG_FUNCTION_ARGS)
Definition: sequence.c:889
void seq_mask(char *page, BlockNumber blkno)
Definition: sequence.c:1884
Datum nextval(PG_FUNCTION_ARGS)
Definition: sequence.c:585
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:615
void SequenceChangePersistence(Oid relid, char newrelpersistence)
Definition: sequence.c:540
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1588
static HTAB * seqhashtab
Definition: sequence.c:90
Datum pg_sequence_last_value(PG_FUNCTION_ARGS)
Definition: sequence.c:1780
Datum currval_oid(PG_FUNCTION_ARGS)
Definition: sequence.c:858
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:937
List * sequence_options(Oid relid)
Definition: sequence.c:1702
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
Definition: sequence.c:1255
SeqTableData * SeqTable
Definition: sequence.c:88
void seq_redo(XLogReaderState *record)
Definition: sequence.c:1816
struct SeqTableData SeqTableData
void ResetSequenceCaches(void)
Definition: sequence.c:1869
static void create_seq_hashtable(void)
Definition: sequence.c:1105
static Relation lock_and_open_sequence(SeqTable seq)
Definition: sequence.c:1077
void DeleteSequenceTuple(Oid relid)
Definition: sequence.c:562
#define SEQ_COL_LASTVAL
Definition: sequence.h:38
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
#define SEQ_COL_CALLED
Definition: sequence.h:40
#define SEQ_COL_LASTCOL
Definition: sequence.h:43
#define SEQ_COL_LOG
Definition: sequence.h:39
#define SEQ_COL_FIRSTCOL
Definition: sequence.h:42
struct xl_seq_rec xl_seq_rec
#define XLOG_SEQ_LOG
Definition: sequence.h:46
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:374
void smgrclose(SMgrRelation reln)
Definition: smgr.c:260
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:150
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:138
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
PGPROC * MyProc
Definition: proc.c:66
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:185
bool is_not_null
Definition: parsenodes.h:725
RangeVar * sequence
char * defname
Definition: parsenodes.h:809
Node * arg
Definition: parsenodes.h:810
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
ItemPointerData t_ctid
LocalTransactionId lxid
Definition: proc.h:183
RangeVar::relname
char * relname
Definition: primnodes.h:74
bool rd_islocaltemp
Definition: rel.h:61
RelFileLocator rd_locator
Definition: rel.h:57
Form_pg_class rd_rel
Definition: rel.h:111
RelFileNumber filenumber
Definition: sequence.c:78
LocalTransactionId lxid
Definition: sequence.c:79
int64 increment
Definition: sequence.c:84
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
RelFileLocator locator
Definition: sequence.h:50
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:182
@ RELOID
Definition: syscache.h:89
@ SEQRELID
Definition: syscache.h:93
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:191
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:675
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
#define FrozenTransactionId
Definition: transam.h:33
#define InvalidTransactionId
Definition: transam.h:31
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:411
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:429
Boolean * makeBoolean(bool val)
Definition: value.c:49
Float * makeFloat(char *numericStr)
Definition: value.c:37
#define boolVal(v)
Definition: value.h:81
#define strVal(v)
Definition: value.h:82
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3396
TransactionId GetTopTransactionId(void)
Definition: xact.c:417
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6052
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:351
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:243
void XLogBeginInsert(void)
Definition: xloginsert.c:150
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:416
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:329