mirror of
https://github.com/postgres/postgres.git
synced 2025-10-15 00:02:00 -04:00
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
This commit is contained in:
parent
97ca67377a
commit
ba3d93b2e8
@ -106,7 +106,9 @@ static Form_pg_sequence_data read_seq_tuple(Relation rel,
|
||||
static void init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
bool isInit,
|
||||
Form_pg_sequence seqform,
|
||||
Form_pg_sequence_data seqdataform,
|
||||
int64 *last_value,
|
||||
bool *reset_state,
|
||||
bool *is_called,
|
||||
bool *need_seq_rewrite,
|
||||
List **owned_by);
|
||||
static void do_setval(Oid relid, int64 next, bool iscalled);
|
||||
@ -121,7 +123,9 @@ ObjectAddress
|
||||
DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
|
||||
{
|
||||
FormData_pg_sequence seqform;
|
||||
FormData_pg_sequence_data seqdataform;
|
||||
int64 last_value;
|
||||
bool reset_state;
|
||||
bool is_called;
|
||||
bool need_seq_rewrite;
|
||||
List *owned_by;
|
||||
CreateStmt *stmt = makeNode(CreateStmt);
|
||||
@ -164,7 +168,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
|
||||
|
||||
/* Check and set all option values */
|
||||
init_params(pstate, seq->options, seq->for_identity, true,
|
||||
&seqform, &seqdataform,
|
||||
&seqform, &last_value, &reset_state, &is_called,
|
||||
&need_seq_rewrite, &owned_by);
|
||||
|
||||
/*
|
||||
@ -179,7 +183,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
|
||||
{
|
||||
case SEQ_COL_LASTVAL:
|
||||
coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
|
||||
value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
|
||||
value[i - 1] = Int64GetDatumFast(last_value);
|
||||
break;
|
||||
case SEQ_COL_LOG:
|
||||
coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid);
|
||||
@ -448,6 +452,9 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
|
||||
ObjectAddress address;
|
||||
Relation rel;
|
||||
HeapTuple seqtuple;
|
||||
bool reset_state = false;
|
||||
bool is_called;
|
||||
int64 last_value;
|
||||
HeapTuple newdatatuple;
|
||||
|
||||
/* Open and lock sequence, and check for ownership along the way. */
|
||||
@ -481,12 +488,14 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
|
||||
/* copy the existing sequence data tuple, so it can be modified locally */
|
||||
newdatatuple = heap_copytuple(&datatuple);
|
||||
newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
|
||||
last_value = newdataform->last_value;
|
||||
is_called = newdataform->is_called;
|
||||
|
||||
UnlockReleaseBuffer(buf);
|
||||
|
||||
/* Check and set new values */
|
||||
init_params(pstate, stmt->options, stmt->for_identity, false,
|
||||
seqform, newdataform,
|
||||
seqform, &last_value, &reset_state, &is_called,
|
||||
&need_seq_rewrite, &owned_by);
|
||||
|
||||
/* If needed, rewrite the sequence relation itself */
|
||||
@ -513,6 +522,10 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
|
||||
/*
|
||||
* Insert the modified tuple into the new storage file.
|
||||
*/
|
||||
newdataform->last_value = last_value;
|
||||
newdataform->is_called = is_called;
|
||||
if (reset_state)
|
||||
newdataform->log_cnt = 0;
|
||||
fill_seq_with_data(seqrel, newdatatuple);
|
||||
}
|
||||
|
||||
@ -1236,17 +1249,19 @@ read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
|
||||
/*
|
||||
* init_params: process the options list of CREATE or ALTER SEQUENCE, and
|
||||
* store the values into appropriate fields of seqform, for changes that go
|
||||
* into the pg_sequence catalog, and fields of seqdataform for changes to the
|
||||
* sequence relation itself. Set *need_seq_rewrite to true if we changed any
|
||||
* parameters that require rewriting the sequence's relation (interesting for
|
||||
* ALTER SEQUENCE). Also set *owned_by to any OWNED BY option, or to NIL if
|
||||
* there is none.
|
||||
* into the pg_sequence catalog, and fields for changes to the sequence
|
||||
* relation itself (*is_called, *last_value and *reset_state). Set
|
||||
* *need_seq_rewrite to true if we changed any parameters that require
|
||||
* rewriting the sequence's relation (interesting for ALTER SEQUENCE). Also
|
||||
* set *owned_by to any OWNED BY option, or to NIL if there is none. Set
|
||||
* *reset_state to true if the internal state of the sequence needs to be
|
||||
* reset, affecting future nextval() calls, for example with WAL logging.
|
||||
*
|
||||
* If isInit is true, fill any unspecified options with default values;
|
||||
* otherwise, do not change existing options that aren't explicitly overridden.
|
||||
*
|
||||
* Note: we force a sequence rewrite whenever we change parameters that affect
|
||||
* generation of future sequence values, even if the seqdataform per se is not
|
||||
* generation of future sequence values, even if the metadata per se is not
|
||||
* changed. This allows ALTER SEQUENCE to behave transactionally. Currently,
|
||||
* the only option that doesn't cause that is OWNED BY. It's *necessary* for
|
||||
* ALTER SEQUENCE OWNED BY to not rewrite the sequence, because that would
|
||||
@ -1257,7 +1272,9 @@ static void
|
||||
init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
bool isInit,
|
||||
Form_pg_sequence seqform,
|
||||
Form_pg_sequence_data seqdataform,
|
||||
int64 *last_value,
|
||||
bool *reset_state,
|
||||
bool *is_called,
|
||||
bool *need_seq_rewrite,
|
||||
List **owned_by)
|
||||
{
|
||||
@ -1363,11 +1380,11 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
}
|
||||
|
||||
/*
|
||||
* We must reset log_cnt when isInit or when changing any parameters that
|
||||
* would affect future nextval allocations.
|
||||
* We must reset the state of the sequence when isInit or when changing
|
||||
* any parameters that would affect future nextval allocations.
|
||||
*/
|
||||
if (isInit)
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
|
||||
/* AS type */
|
||||
if (as_type != NULL)
|
||||
@ -1416,7 +1433,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("INCREMENT must not be zero")));
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit)
|
||||
{
|
||||
@ -1428,7 +1445,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
{
|
||||
seqform->seqcycle = boolVal(is_cycled->arg);
|
||||
Assert(BoolIsValid(seqform->seqcycle));
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit)
|
||||
{
|
||||
@ -1439,7 +1456,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
if (max_value != NULL && max_value->arg)
|
||||
{
|
||||
seqform->seqmax = defGetInt64(max_value);
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit || max_value != NULL || reset_max_value)
|
||||
{
|
||||
@ -1455,7 +1472,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
}
|
||||
else
|
||||
seqform->seqmax = -1; /* descending seq */
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
if (min_value != NULL && min_value->arg)
|
||||
{
|
||||
seqform->seqmin = defGetInt64(min_value);
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit || min_value != NULL || reset_min_value)
|
||||
{
|
||||
@ -1487,7 +1504,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
}
|
||||
else
|
||||
seqform->seqmin = 1; /* ascending seq */
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
if (restart_value != NULL)
|
||||
{
|
||||
if (restart_value->arg != NULL)
|
||||
seqdataform->last_value = defGetInt64(restart_value);
|
||||
*last_value = defGetInt64(restart_value);
|
||||
else
|
||||
seqdataform->last_value = seqform->seqstart;
|
||||
seqdataform->is_called = false;
|
||||
seqdataform->log_cnt = 0;
|
||||
*last_value = seqform->seqstart;
|
||||
*is_called = false;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit)
|
||||
{
|
||||
seqdataform->last_value = seqform->seqstart;
|
||||
seqdataform->is_called = false;
|
||||
*last_value = seqform->seqstart;
|
||||
*is_called = false;
|
||||
}
|
||||
|
||||
/* crosscheck RESTART (or current value, if changing MIN/MAX) */
|
||||
if (seqdataform->last_value < seqform->seqmin)
|
||||
if (*last_value < seqform->seqmin)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("RESTART value (%" PRId64 ") cannot be less than MINVALUE (%" PRId64 ")",
|
||||
seqdataform->last_value,
|
||||
*last_value,
|
||||
seqform->seqmin)));
|
||||
if (seqdataform->last_value > seqform->seqmax)
|
||||
if (*last_value > seqform->seqmax)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("RESTART value (%" PRId64 ") cannot be greater than MAXVALUE (%" PRId64 ")",
|
||||
seqdataform->last_value,
|
||||
*last_value,
|
||||
seqform->seqmax)));
|
||||
|
||||
/* CACHE */
|
||||
@ -1573,7 +1590,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("CACHE (%" PRId64 ") must be greater than zero",
|
||||
seqform->seqcache)));
|
||||
seqdataform->log_cnt = 0;
|
||||
*reset_state = true;
|
||||
}
|
||||
else if (isInit)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user