@@ -98,11 +98,9 @@ static void create_seq_hashtable(void);
9898static void init_sequence (Oid relid ,SeqTable * p_elm ,Relation * p_rel );
9999static Form_pg_sequence_data read_seq_tuple (Relation rel ,
100100Buffer * buf ,HeapTuple seqdatatuple );
101- static LOCKMODE alter_sequence_get_lock_level (List * options );
102101static void init_params (ParseState * pstate ,List * options ,bool for_identity ,
103102bool isInit ,
104103Form_pg_sequence seqform ,
105- bool * changed_seqform ,
106104Form_pg_sequence_data seqdataform ,List * * owned_by );
107105static void do_setval (Oid relid ,int64 next ,bool iscalled );
108106static void process_owned_by (Relation seqrel ,List * owned_by ,bool for_identity );
@@ -117,7 +115,6 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
117115{
118116FormData_pg_sequence seqform ;
119117FormData_pg_sequence_data seqdataform ;
120- bool changed_seqform = false;/* not used here */
121118List * owned_by ;
122119CreateStmt * stmt = makeNode (CreateStmt );
123120Oid seqoid ;
@@ -156,7 +153,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
156153}
157154
158155/* Check and set all option values */
159- init_params (pstate ,seq -> options ,seq -> for_identity , true,& seqform ,& changed_seqform , & seqdataform ,& owned_by );
156+ init_params (pstate ,seq -> options ,seq -> for_identity , true,& seqform ,& seqdataform ,& owned_by );
160157
161158/*
162159 * Create relation (and fill value[] and null[] for the tuple)
@@ -417,19 +414,18 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
417414SeqTable elm ;
418415Relation seqrel ;
419416Buffer buf ;
420- HeapTupleData seqdatatuple ;
417+ HeapTupleData datatuple ;
421418Form_pg_sequence seqform ;
422- Form_pg_sequence_data seqdata ;
423- FormData_pg_sequence_data newseqdata ;
424- bool changed_seqform = false;
419+ Form_pg_sequence_data newdataform ;
425420List * owned_by ;
426421ObjectAddress address ;
427422Relation rel ;
428- HeapTuple tuple ;
423+ HeapTuple seqtuple ;
424+ HeapTuple newdatatuple ;
429425
430426/* Open and lock sequence. */
431427relid = RangeVarGetRelid (stmt -> sequence ,
432- alter_sequence_get_lock_level ( stmt -> options ) ,
428+ ShareRowExclusiveLock ,
433429stmt -> missing_ok );
434430if (relid == InvalidOid )
435431{
@@ -447,22 +443,26 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
447443stmt -> sequence -> relname );
448444
449445rel = heap_open (SequenceRelationId ,RowExclusiveLock );
450- tuple = SearchSysCacheCopy1 (SEQRELID ,
451- ObjectIdGetDatum (relid ));
452- if (!HeapTupleIsValid (tuple ))
446+ seqtuple = SearchSysCacheCopy1 (SEQRELID ,
447+ ObjectIdGetDatum (relid ));
448+ if (!HeapTupleIsValid (seqtuple ))
453449elog (ERROR ,"cache lookup failed for sequence %u" ,
454450relid );
455451
456- seqform = (Form_pg_sequence )GETSTRUCT (tuple );
452+ seqform = (Form_pg_sequence )GETSTRUCT (seqtuple );
457453
458454/* lock page's buffer and read tuple into new sequence structure */
459- seqdata = read_seq_tuple (seqrel ,& buf ,& seqdatatuple );
455+ ( void ) read_seq_tuple (seqrel ,& buf ,& datatuple );
460456
461- /* Copy old sequence data into workspace */
462- memcpy (& newseqdata ,seqdata ,sizeof (FormData_pg_sequence_data ));
457+ /* copy the existing sequence data tuple, so it can be modified localy */
458+ newdatatuple = heap_copytuple (& datatuple );
459+ newdataform = (Form_pg_sequence_data )GETSTRUCT (newdatatuple );
460+
461+ UnlockReleaseBuffer (buf );
463462
464463/* Check and set new values */
465- init_params (pstate ,stmt -> options ,stmt -> for_identity , false,seqform ,& changed_seqform ,& newseqdata ,& owned_by );
464+ init_params (pstate ,stmt -> options ,stmt -> for_identity , false,seqform ,
465+ newdataform ,& owned_by );
466466
467467/* Clear local cache so that we don't think we have cached numbers */
468468/* Note that we do not change the currval() state */
@@ -472,36 +472,19 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
472472if (RelationNeedsWAL (seqrel ))
473473GetTopTransactionId ();
474474
475- /* Now okay to update the on-disk tuple */
476- START_CRIT_SECTION ();
477-
478- memcpy (seqdata ,& newseqdata ,sizeof (FormData_pg_sequence_data ));
479-
480- MarkBufferDirty (buf );
481-
482- /* XLOG stuff */
483- if (RelationNeedsWAL (seqrel ))
484- {
485- xl_seq_rec xlrec ;
486- XLogRecPtr recptr ;
487- Page page = BufferGetPage (buf );
488-
489- XLogBeginInsert ();
490- XLogRegisterBuffer (0 ,buf ,REGBUF_WILL_INIT );
491-
492- xlrec .node = seqrel -> rd_node ;
493- XLogRegisterData ((char * )& xlrec ,sizeof (xl_seq_rec ));
494-
495- XLogRegisterData ((char * )seqdatatuple .t_data ,seqdatatuple .t_len );
496-
497- recptr = XLogInsert (RM_SEQ_ID ,XLOG_SEQ_LOG );
498-
499- PageSetLSN (page ,recptr );
500- }
501-
502- END_CRIT_SECTION ();
475+ /*
476+ * Create a new storage file for the sequence, making the state changes
477+ * transactional. We want to keep the sequence's relfrozenxid at 0, since
478+ * it won't contain any unfrozen XIDs. Same with relminmxid, since a
479+ * sequence will never contain multixacts.
480+ */
481+ RelationSetNewRelfilenode (seqrel ,seqrel -> rd_rel -> relpersistence ,
482+ InvalidTransactionId ,InvalidMultiXactId );
503483
504- UnlockReleaseBuffer (buf );
484+ /*
485+ * Insert the modified tuple into the new storage file.
486+ */
487+ fill_seq_with_data (seqrel ,newdatatuple );
505488
506489/* process OWNED BY if given */
507490if (owned_by )
@@ -511,10 +494,9 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
511494
512495ObjectAddressSet (address ,RelationRelationId ,relid );
513496
514- if (changed_seqform )
515- CatalogTupleUpdate (rel ,& tuple -> t_self ,tuple );
516- heap_close (rel ,RowExclusiveLock );
497+ CatalogTupleUpdate (rel ,& seqtuple -> t_self ,seqtuple );
517498
499+ heap_close (rel ,RowExclusiveLock );
518500relation_close (seqrel ,NoLock );
519501
520502return address ;
@@ -1219,30 +1201,6 @@ read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
12191201return seq ;
12201202}
12211203
1222- /*
1223- * Check the sequence options list and return the appropriate lock level for
1224- * ALTER SEQUENCE.
1225- *
1226- * Most sequence option changes require a self-exclusive lock and should block
1227- * concurrent nextval() et al. But RESTART does not, because it's not
1228- * transactional. Also take a lower lock if no option at all is present.
1229- */
1230- static LOCKMODE
1231- alter_sequence_get_lock_level (List * options )
1232- {
1233- ListCell * option ;
1234-
1235- foreach (option ,options )
1236- {
1237- DefElem * defel = (DefElem * )lfirst (option );
1238-
1239- if (strcmp (defel -> defname ,"restart" )!= 0 )
1240- return ShareRowExclusiveLock ;
1241- }
1242-
1243- return RowExclusiveLock ;
1244- }
1245-
12461204/*
12471205 * init_params: process the options list of CREATE or ALTER SEQUENCE, and
12481206 * store the values into appropriate fields of seqform, for changes that go
@@ -1258,7 +1216,6 @@ static void
12581216init_params (ParseState * pstate ,List * options ,bool for_identity ,
12591217bool isInit ,
12601218Form_pg_sequence seqform ,
1261- bool * changed_seqform ,
12621219Form_pg_sequence_data seqdataform ,
12631220List * * owned_by )
12641221{
@@ -1378,8 +1335,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
13781335defel -> defname );
13791336}
13801337
1381- * changed_seqform = false;
1382-
13831338/*
13841339 * We must reset log_cnt when isInit or when changing any parameters that
13851340 * would affect future nextval allocations.
@@ -1420,19 +1375,16 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14201375}
14211376
14221377seqform -> seqtypid = newtypid ;
1423- * changed_seqform = true;
14241378}
14251379else if (isInit )
14261380{
14271381seqform -> seqtypid = INT8OID ;
1428- * changed_seqform = true;
14291382}
14301383
14311384/* INCREMENT BY */
14321385if (increment_by != NULL )
14331386{
14341387seqform -> seqincrement = defGetInt64 (increment_by );
1435- * changed_seqform = true;
14361388if (seqform -> seqincrement == 0 )
14371389ereport (ERROR ,
14381390(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
@@ -1442,28 +1394,24 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14421394else if (isInit )
14431395{
14441396seqform -> seqincrement = 1 ;
1445- * changed_seqform = true;
14461397}
14471398
14481399/* CYCLE */
14491400if (is_cycled != NULL )
14501401{
14511402seqform -> seqcycle = intVal (is_cycled -> arg );
1452- * changed_seqform = true;
14531403Assert (BoolIsValid (seqform -> seqcycle ));
14541404seqdataform -> log_cnt = 0 ;
14551405}
14561406else if (isInit )
14571407{
14581408seqform -> seqcycle = false;
1459- * changed_seqform = true;
14601409}
14611410
14621411/* MAXVALUE (null arg means NO MAXVALUE) */
14631412if (max_value != NULL && max_value -> arg )
14641413{
14651414seqform -> seqmax = defGetInt64 (max_value );
1466- * changed_seqform = true;
14671415seqdataform -> log_cnt = 0 ;
14681416}
14691417else if (isInit || max_value != NULL || reset_max_value )
@@ -1480,7 +1428,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14801428}
14811429else
14821430seqform -> seqmax = -1 ;/* descending seq */
1483- * changed_seqform = true;
14841431seqdataform -> log_cnt = 0 ;
14851432}
14861433
@@ -1502,7 +1449,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15021449if (min_value != NULL && min_value -> arg )
15031450{
15041451seqform -> seqmin = defGetInt64 (min_value );
1505- * changed_seqform = true;
15061452seqdataform -> log_cnt = 0 ;
15071453}
15081454else if (isInit || min_value != NULL || reset_min_value )
@@ -1519,7 +1465,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15191465}
15201466else
15211467seqform -> seqmin = 1 ;/* ascending seq */
1522- * changed_seqform = true;
15231468seqdataform -> log_cnt = 0 ;
15241469}
15251470
@@ -1555,15 +1500,13 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15551500if (start_value != NULL )
15561501{
15571502seqform -> seqstart = defGetInt64 (start_value );
1558- * changed_seqform = true;
15591503}
15601504else if (isInit )
15611505{
15621506if (seqform -> seqincrement > 0 )
15631507seqform -> seqstart = seqform -> seqmin ;/* ascending seq */
15641508else
15651509seqform -> seqstart = seqform -> seqmax ;/* descending seq */
1566- * changed_seqform = true;
15671510}
15681511
15691512/* crosscheck START */
@@ -1638,7 +1581,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
16381581if (cache_value != NULL )
16391582{
16401583seqform -> seqcache = defGetInt64 (cache_value );
1641- * changed_seqform = true;
16421584if (seqform -> seqcache <=0 )
16431585{
16441586char buf [100 ];
@@ -1654,7 +1596,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
16541596else if (isInit )
16551597{
16561598seqform -> seqcache = 1 ;
1657- * changed_seqform = true;
16581599}
16591600}
16601601