Commit 3486bcf9 authored by Tom Lane's avatar Tom Lane

Fix pg_dump's logic for eliding sequence limits that match the defaults.

The previous coding here applied atoi() to strings that could represent
values too large to fit in an int.  If the overflowed value happened to
match one of the cases it was looking for, it would drop that limit
value from the output, leading to incorrect restoration of the sequence.

Avoid the unsafe behavior, and also make the logic cleaner by explicitly
calculating the default min/max values for the appropriate kind of
sequence.

Reported and patched by Alexey Bashtanov, though I whacked his patch
around a bit.  Back-patch to v10 where the faulty logic was added.

Discussion: https://postgr.es/m/cb85a9a5-946b-c7c4-9cf2-6cd6e25d7a33@imap.cc
parent 9a89f6d8
......@@ -16843,6 +16843,10 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
*seqtype;
bool cycled;
bool is_ascending;
int64 default_minv,
default_maxv;
char bufm[32],
bufx[32];
PQExpBuffer query = createPQExpBuffer();
PQExpBuffer delqry = createPQExpBuffer();
PQExpBuffer labelq = createPQExpBuffer();
......@@ -16912,40 +16916,41 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
cache = PQgetvalue(res, 0, 5);
cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
is_ascending = incby[0] != '-';
if (is_ascending && atoi(minv) == 1)
minv = NULL;
if (!is_ascending && atoi(maxv) == -1)
maxv = NULL;
/* Calculate default limits for a sequence of this type */
is_ascending = (incby[0] != '-');
if (strcmp(seqtype, "smallint") == 0)
{
if (!is_ascending && atoi(minv) == PG_INT16_MIN)
minv = NULL;
if (is_ascending && atoi(maxv) == PG_INT16_MAX)
maxv = NULL;
default_minv = is_ascending ? 1 : PG_INT16_MIN;
default_maxv = is_ascending ? PG_INT16_MAX : -1;
}
else if (strcmp(seqtype, "integer") == 0)
{
if (!is_ascending && atoi(minv) == PG_INT32_MIN)
minv = NULL;
if (is_ascending && atoi(maxv) == PG_INT32_MAX)
maxv = NULL;
default_minv = is_ascending ? 1 : PG_INT32_MIN;
default_maxv = is_ascending ? PG_INT32_MAX : -1;
}
else if (strcmp(seqtype, "bigint") == 0)
{
char bufm[100],
bufx[100];
default_minv = is_ascending ? 1 : PG_INT64_MIN;
default_maxv = is_ascending ? PG_INT64_MAX : -1;
}
else
{
exit_horribly(NULL, "unrecognized sequence type: %s\n", seqtype);
default_minv = default_maxv = 0; /* keep compiler quiet */
}
snprintf(bufm, sizeof(bufm), INT64_FORMAT, PG_INT64_MIN);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, PG_INT64_MAX);
/*
* 64-bit strtol() isn't very portable, so convert the limits to strings
* and compare that way.
*/
snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv);
if (!is_ascending && strcmp(minv, bufm) == 0)
minv = NULL;
if (is_ascending && strcmp(maxv, bufx) == 0)
maxv = NULL;
}
/* Don't print minv/maxv if they match the respective default limit */
if (strcmp(minv, bufm) == 0)
minv = NULL;
if (strcmp(maxv, bufx) == 0)
maxv = NULL;
/*
* DROP must be fully qualified in case same name appears in pg_catalog
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment