Skip to content

Commit ba3d93b

Browse files
committed
Refactor init_params() in sequence.c to not use FormData_pg_sequence_data
init_params() sets up "last_value" and "is_called" for a sequence relation holdind its metadata, based on the sequence properties in pg_sequences. "log_cnt" is the third property that can be updated in this routine for FormData_pg_sequence_data, tracking when WAL records should be generated for a sequence after nextval() iterations. This routine is called when creating or altering a sequence. This commit refactors init_params() to not depend anymore on FormData_pg_sequence_data, removing traces of it in sequence.c, making easier the manipulation of metadata related to sequences. The knowledge about "log_cnt" is replaced with a more general "reset_state" flag, to let the caller know if the sequence state should be reset. In the case of in-core sequences, this relates to WAL logging. We still need to depend on FormData_pg_sequence. Author: Michael Paquier <michael@paquier.xyz> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Reviewed-by: Tomas Vondra <tomas@vondra.me> Discussion: https://postgr.es/m/ZWlohtKAs0uVVpZ3@paquier.xyz
1 parent 97ca673 commit ba3d93b

File tree

1 file changed

+49
-32
lines changed

1 file changed

+49
-32
lines changed

src/backend/commands/sequence.c

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ static Form_pg_sequence_data read_seq_tuple(Relation rel,
106106
static void init_params(ParseState *pstate, List *options, bool for_identity,
107107
bool isInit,
108108
Form_pg_sequence seqform,
109-
Form_pg_sequence_data seqdataform,
109+
int64 *last_value,
110+
bool *reset_state,
111+
bool *is_called,
110112
bool *need_seq_rewrite,
111113
List **owned_by);
112114
static void do_setval(Oid relid, int64 next, bool iscalled);
@@ -121,7 +123,9 @@ ObjectAddress
121123
DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
122124
{
123125
FormData_pg_sequence seqform;
124-
FormData_pg_sequence_data seqdataform;
126+
int64 last_value;
127+
bool reset_state;
128+
bool is_called;
125129
bool need_seq_rewrite;
126130
List *owned_by;
127131
CreateStmt *stmt = makeNode(CreateStmt);
@@ -164,7 +168,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
164168

165169
/* Check and set all option values */
166170
init_params(pstate, seq->options, seq->for_identity, true,
167-
&seqform, &seqdataform,
171+
&seqform, &last_value, &reset_state, &is_called,
168172
&need_seq_rewrite, &owned_by);
169173

170174
/*
@@ -179,7 +183,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
179183
{
180184
case SEQ_COL_LASTVAL:
181185
coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
182-
value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
186+
value[i - 1] = Int64GetDatumFast(last_value);
183187
break;
184188
case SEQ_COL_LOG:
185189
coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid);
@@ -448,6 +452,9 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
448452
ObjectAddress address;
449453
Relation rel;
450454
HeapTuple seqtuple;
455+
bool reset_state = false;
456+
bool is_called;
457+
int64 last_value;
451458
HeapTuple newdatatuple;
452459

453460
/* Open and lock sequence, and check for ownership along the way. */
@@ -481,12 +488,14 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
481488
/* copy the existing sequence data tuple, so it can be modified locally */
482489
newdatatuple = heap_copytuple(&datatuple);
483490
newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
491+
last_value = newdataform->last_value;
492+
is_called = newdataform->is_called;
484493

485494
UnlockReleaseBuffer(buf);
486495

487496
/* Check and set new values */
488497
init_params(pstate, stmt->options, stmt->for_identity, false,
489-
seqform, newdataform,
498+
seqform, &last_value, &reset_state, &is_called,
490499
&need_seq_rewrite, &owned_by);
491500

492501
/* If needed, rewrite the sequence relation itself */
@@ -513,6 +522,10 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
513522
/*
514523
* Insert the modified tuple into the new storage file.
515524
*/
525+
newdataform->last_value = last_value;
526+
newdataform->is_called = is_called;
527+
if (reset_state)
528+
newdataform->log_cnt = 0;
516529
fill_seq_with_data(seqrel, newdatatuple);
517530
}
518531

@@ -1236,17 +1249,19 @@ read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
12361249
/*
12371250
* init_params: process the options list of CREATE or ALTER SEQUENCE, and
12381251
* store the values into appropriate fields of seqform, for changes that go
1239-
* into the pg_sequence catalog, and fields of seqdataform for changes to the
1240-
* sequence relation itself. Set *need_seq_rewrite to true if we changed any
1241-
* parameters that require rewriting the sequence's relation (interesting for
1242-
* ALTER SEQUENCE). Also set *owned_by to any OWNED BY option, or to NIL if
1243-
* there is none.
1252+
* into the pg_sequence catalog, and fields for changes to the sequence
1253+
* relation itself (*is_called, *last_value and *reset_state). Set
1254+
* *need_seq_rewrite to true if we changed any parameters that require
1255+
* rewriting the sequence's relation (interesting for ALTER SEQUENCE). Also
1256+
* set *owned_by to any OWNED BY option, or to NIL if there is none. Set
1257+
* *reset_state to true if the internal state of the sequence needs to be
1258+
* reset, affecting future nextval() calls, for example with WAL logging.
12441259
*
12451260
* If isInit is true, fill any unspecified options with default values;
12461261
* otherwise, do not change existing options that aren't explicitly overridden.
12471262
*
12481263
* Note: we force a sequence rewrite whenever we change parameters that affect
1249-
* generation of future sequence values, even if the seqdataform per se is not
1264+
* generation of future sequence values, even if the metadata per se is not
12501265
* changed. This allows ALTER SEQUENCE to behave transactionally. Currently,
12511266
* the only option that doesn't cause that is OWNED BY. It's *necessary* for
12521267
* ALTER SEQUENCE OWNED BY to not rewrite the sequence, because that would
@@ -1257,7 +1272,9 @@ static void
12571272
init_params(ParseState *pstate, List *options, bool for_identity,
12581273
bool isInit,
12591274
Form_pg_sequence seqform,
1260-
Form_pg_sequence_data seqdataform,
1275+
int64 *last_value,
1276+
bool *reset_state,
1277+
bool *is_called,
12611278
bool *need_seq_rewrite,
12621279
List **owned_by)
12631280
{
@@ -1363,11 +1380,11 @@ init_params(ParseState *pstate, List *options, bool for_identity,
13631380
}
13641381

13651382
/*
1366-
* We must reset log_cnt when isInit or when changing any parameters that
1367-
* would affect future nextval allocations.
1383+
* We must reset the state of the sequence when isInit or when changing
1384+
* any parameters that would affect future nextval allocations.
13681385
*/
13691386
if (isInit)
1370-
seqdataform->log_cnt = 0;
1387+
*reset_state = true;
13711388

13721389
/* AS type */
13731390
if (as_type != NULL)
@@ -1416,7 +1433,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14161433
ereport(ERROR,
14171434
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
14181435
errmsg("INCREMENT must not be zero")));
1419-
seqdataform->log_cnt = 0;
1436+
*reset_state = true;
14201437
}
14211438
else if (isInit)
14221439
{
@@ -1428,7 +1445,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14281445
{
14291446
seqform->seqcycle = boolVal(is_cycled->arg);
14301447
Assert(BoolIsValid(seqform->seqcycle));
1431-
seqdataform->log_cnt = 0;
1448+
*reset_state = true;
14321449
}
14331450
else if (isInit)
14341451
{
@@ -1439,7 +1456,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14391456
if (max_value != NULL && max_value->arg)
14401457
{
14411458
seqform->seqmax = defGetInt64(max_value);
1442-
seqdataform->log_cnt = 0;
1459+
*reset_state = true;
14431460
}
14441461
else if (isInit || max_value != NULL || reset_max_value)
14451462
{
@@ -1455,7 +1472,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14551472
}
14561473
else
14571474
seqform->seqmax = -1; /* descending seq */
1458-
seqdataform->log_cnt = 0;
1475+
*reset_state = true;
14591476
}
14601477

14611478
/* Validate maximum value. No need to check INT8 as seqmax is an int64 */
@@ -1471,7 +1488,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14711488
if (min_value != NULL && min_value->arg)
14721489
{
14731490
seqform->seqmin = defGetInt64(min_value);
1474-
seqdataform->log_cnt = 0;
1491+
*reset_state = true;
14751492
}
14761493
else if (isInit || min_value != NULL || reset_min_value)
14771494
{
@@ -1487,7 +1504,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14871504
}
14881505
else
14891506
seqform->seqmin = 1; /* ascending seq */
1490-
seqdataform->log_cnt = 0;
1507+
*reset_state = true;
14911508
}
14921509

14931510
/* Validate minimum value. No need to check INT8 as seqmin is an int64 */
@@ -1538,30 +1555,30 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15381555
if (restart_value != NULL)
15391556
{
15401557
if (restart_value->arg != NULL)
1541-
seqdataform->last_value = defGetInt64(restart_value);
1558+
*last_value = defGetInt64(restart_value);
15421559
else
1543-
seqdataform->last_value = seqform->seqstart;
1544-
seqdataform->is_called = false;
1545-
seqdataform->log_cnt = 0;
1560+
*last_value = seqform->seqstart;
1561+
*is_called = false;
1562+
*reset_state = true;
15461563
}
15471564
else if (isInit)
15481565
{
1549-
seqdataform->last_value = seqform->seqstart;
1550-
seqdataform->is_called = false;
1566+
*last_value = seqform->seqstart;
1567+
*is_called = false;
15511568
}
15521569

15531570
/* crosscheck RESTART (or current value, if changing MIN/MAX) */
1554-
if (seqdataform->last_value < seqform->seqmin)
1571+
if (*last_value < seqform->seqmin)
15551572
ereport(ERROR,
15561573
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
15571574
errmsg("RESTART value (%" PRId64 ") cannot be less than MINVALUE (%" PRId64 ")",
1558-
seqdataform->last_value,
1575+
*last_value,
15591576
seqform->seqmin)));
1560-
if (seqdataform->last_value > seqform->seqmax)
1577+
if (*last_value > seqform->seqmax)
15611578
ereport(ERROR,
15621579
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
15631580
errmsg("RESTART value (%" PRId64 ") cannot be greater than MAXVALUE (%" PRId64 ")",
1564-
seqdataform->last_value,
1581+
*last_value,
15651582
seqform->seqmax)));
15661583

15671584
/* CACHE */
@@ -1573,7 +1590,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15731590
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
15741591
errmsg("CACHE (%" PRId64 ") must be greater than zero",
15751592
seqform->seqcache)));
1576-
seqdataform->log_cnt = 0;
1593+
*reset_state = true;
15771594
}
15781595
else if (isInit)
15791596
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy