@@ -98,11 +98,9 @@ static void create_seq_hashtable(void);
98
98
static void init_sequence (Oid relid , SeqTable * p_elm , Relation * p_rel );
99
99
static Form_pg_sequence_data read_seq_tuple (Relation rel ,
100
100
Buffer * buf , HeapTuple seqdatatuple );
101
- static LOCKMODE alter_sequence_get_lock_level (List * options );
102
101
static void init_params (ParseState * pstate , List * options , bool for_identity ,
103
102
bool isInit ,
104
103
Form_pg_sequence seqform ,
105
- bool * changed_seqform ,
106
104
Form_pg_sequence_data seqdataform , List * * owned_by );
107
105
static void do_setval (Oid relid , int64 next , bool iscalled );
108
106
static void process_owned_by (Relation seqrel , List * owned_by , bool for_identity );
@@ -117,7 +115,6 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
117
115
{
118
116
FormData_pg_sequence seqform ;
119
117
FormData_pg_sequence_data seqdataform ;
120
- bool changed_seqform = false; /* not used here */
121
118
List * owned_by ;
122
119
CreateStmt * stmt = makeNode (CreateStmt );
123
120
Oid seqoid ;
@@ -156,7 +153,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
156
153
}
157
154
158
155
/* 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 );
160
157
161
158
/*
162
159
* Create relation (and fill value[] and null[] for the tuple)
@@ -417,19 +414,18 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
417
414
SeqTable elm ;
418
415
Relation seqrel ;
419
416
Buffer buf ;
420
- HeapTupleData seqdatatuple ;
417
+ HeapTupleData datatuple ;
421
418
Form_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 ;
425
420
List * owned_by ;
426
421
ObjectAddress address ;
427
422
Relation rel ;
428
- HeapTuple tuple ;
423
+ HeapTuple seqtuple ;
424
+ HeapTuple newdatatuple ;
429
425
430
426
/* Open and lock sequence. */
431
427
relid = RangeVarGetRelid (stmt -> sequence ,
432
- alter_sequence_get_lock_level ( stmt -> options ) ,
428
+ ShareRowExclusiveLock ,
433
429
stmt -> missing_ok );
434
430
if (relid == InvalidOid )
435
431
{
@@ -447,22 +443,26 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
447
443
stmt -> sequence -> relname );
448
444
449
445
rel = 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 ))
453
449
elog (ERROR , "cache lookup failed for sequence %u" ,
454
450
relid );
455
451
456
- seqform = (Form_pg_sequence ) GETSTRUCT (tuple );
452
+ seqform = (Form_pg_sequence ) GETSTRUCT (seqtuple );
457
453
458
454
/* 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 );
460
456
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 );
463
462
464
463
/* 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 );
466
466
467
467
/* Clear local cache so that we don't think we have cached numbers */
468
468
/* Note that we do not change the currval() state */
@@ -472,36 +472,19 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
472
472
if (RelationNeedsWAL (seqrel ))
473
473
GetTopTransactionId ();
474
474
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 );
503
483
504
- UnlockReleaseBuffer (buf );
484
+ /*
485
+ * Insert the modified tuple into the new storage file.
486
+ */
487
+ fill_seq_with_data (seqrel , newdatatuple );
505
488
506
489
/* process OWNED BY if given */
507
490
if (owned_by )
@@ -511,10 +494,9 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
511
494
512
495
ObjectAddressSet (address , RelationRelationId , relid );
513
496
514
- if (changed_seqform )
515
- CatalogTupleUpdate (rel , & tuple -> t_self , tuple );
516
- heap_close (rel , RowExclusiveLock );
497
+ CatalogTupleUpdate (rel , & seqtuple -> t_self , seqtuple );
517
498
499
+ heap_close (rel , RowExclusiveLock );
518
500
relation_close (seqrel , NoLock );
519
501
520
502
return address ;
@@ -1219,30 +1201,6 @@ read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
1219
1201
return seq ;
1220
1202
}
1221
1203
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
-
1246
1204
/*
1247
1205
* init_params: process the options list of CREATE or ALTER SEQUENCE, and
1248
1206
* store the values into appropriate fields of seqform, for changes that go
@@ -1258,7 +1216,6 @@ static void
1258
1216
init_params (ParseState * pstate , List * options , bool for_identity ,
1259
1217
bool isInit ,
1260
1218
Form_pg_sequence seqform ,
1261
- bool * changed_seqform ,
1262
1219
Form_pg_sequence_data seqdataform ,
1263
1220
List * * owned_by )
1264
1221
{
@@ -1378,8 +1335,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1378
1335
defel -> defname );
1379
1336
}
1380
1337
1381
- * changed_seqform = false;
1382
-
1383
1338
/*
1384
1339
* We must reset log_cnt when isInit or when changing any parameters that
1385
1340
* would affect future nextval allocations.
@@ -1420,19 +1375,16 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1420
1375
}
1421
1376
1422
1377
seqform -> seqtypid = newtypid ;
1423
- * changed_seqform = true;
1424
1378
}
1425
1379
else if (isInit )
1426
1380
{
1427
1381
seqform -> seqtypid = INT8OID ;
1428
- * changed_seqform = true;
1429
1382
}
1430
1383
1431
1384
/* INCREMENT BY */
1432
1385
if (increment_by != NULL )
1433
1386
{
1434
1387
seqform -> seqincrement = defGetInt64 (increment_by );
1435
- * changed_seqform = true;
1436
1388
if (seqform -> seqincrement == 0 )
1437
1389
ereport (ERROR ,
1438
1390
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
@@ -1442,28 +1394,24 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1442
1394
else if (isInit )
1443
1395
{
1444
1396
seqform -> seqincrement = 1 ;
1445
- * changed_seqform = true;
1446
1397
}
1447
1398
1448
1399
/* CYCLE */
1449
1400
if (is_cycled != NULL )
1450
1401
{
1451
1402
seqform -> seqcycle = intVal (is_cycled -> arg );
1452
- * changed_seqform = true;
1453
1403
Assert (BoolIsValid (seqform -> seqcycle ));
1454
1404
seqdataform -> log_cnt = 0 ;
1455
1405
}
1456
1406
else if (isInit )
1457
1407
{
1458
1408
seqform -> seqcycle = false;
1459
- * changed_seqform = true;
1460
1409
}
1461
1410
1462
1411
/* MAXVALUE (null arg means NO MAXVALUE) */
1463
1412
if (max_value != NULL && max_value -> arg )
1464
1413
{
1465
1414
seqform -> seqmax = defGetInt64 (max_value );
1466
- * changed_seqform = true;
1467
1415
seqdataform -> log_cnt = 0 ;
1468
1416
}
1469
1417
else if (isInit || max_value != NULL || reset_max_value )
@@ -1480,7 +1428,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1480
1428
}
1481
1429
else
1482
1430
seqform -> seqmax = -1 ; /* descending seq */
1483
- * changed_seqform = true;
1484
1431
seqdataform -> log_cnt = 0 ;
1485
1432
}
1486
1433
@@ -1502,7 +1449,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1502
1449
if (min_value != NULL && min_value -> arg )
1503
1450
{
1504
1451
seqform -> seqmin = defGetInt64 (min_value );
1505
- * changed_seqform = true;
1506
1452
seqdataform -> log_cnt = 0 ;
1507
1453
}
1508
1454
else if (isInit || min_value != NULL || reset_min_value )
@@ -1519,7 +1465,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1519
1465
}
1520
1466
else
1521
1467
seqform -> seqmin = 1 ; /* ascending seq */
1522
- * changed_seqform = true;
1523
1468
seqdataform -> log_cnt = 0 ;
1524
1469
}
1525
1470
@@ -1555,15 +1500,13 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1555
1500
if (start_value != NULL )
1556
1501
{
1557
1502
seqform -> seqstart = defGetInt64 (start_value );
1558
- * changed_seqform = true;
1559
1503
}
1560
1504
else if (isInit )
1561
1505
{
1562
1506
if (seqform -> seqincrement > 0 )
1563
1507
seqform -> seqstart = seqform -> seqmin ; /* ascending seq */
1564
1508
else
1565
1509
seqform -> seqstart = seqform -> seqmax ; /* descending seq */
1566
- * changed_seqform = true;
1567
1510
}
1568
1511
1569
1512
/* crosscheck START */
@@ -1638,7 +1581,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1638
1581
if (cache_value != NULL )
1639
1582
{
1640
1583
seqform -> seqcache = defGetInt64 (cache_value );
1641
- * changed_seqform = true;
1642
1584
if (seqform -> seqcache <= 0 )
1643
1585
{
1644
1586
char buf [100 ];
@@ -1654,7 +1596,6 @@ init_params(ParseState *pstate, List *options, bool for_identity,
1654
1596
else if (isInit )
1655
1597
{
1656
1598
seqform -> seqcache = 1 ;
1657
- * changed_seqform = true;
1658
1599
}
1659
1600
}
1660
1601
0 commit comments