From 23687e925f94e36d2d3172faa053f4540bfbb8d2 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 31 Jul 2024 10:12:41 -0500 Subject: [PATCH] Parse sequence type and integer metadata in dumpSequence(). This commit modifies dumpSequence() to parse all the sequence metadata into the appropriate types instead of carting around string pointers to the PGresult data. Besides allowing us to free the PGresult storage earlier in the function, this eliminates the need to compare min_value and max_value to their respective defaults as strings. This is preparatory work for a follow-up commit that will improve the performance of dumpSequence() in a similar manner to how commit 2329cad1b9 optimized binary_upgrade_set_pg_class_oids(). Reviewed-by: Euler Taveira Discussion: https://postgr.es/m/20240503025140.GA1227404%40nathanxps13 --- src/bin/pg_dump/pg_dump.c | 104 ++++++++++++++++++------------- src/tools/pgindent/typedefs.list | 1 + 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 2b02148559b..9c463137c05 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -104,6 +104,24 @@ typedef struct RelFileNumber toast_index_relfilenumber; /* toast table index filenode */ } BinaryUpgradeClassOidItem; +/* sequence types */ +typedef enum SeqType +{ + SEQTYPE_SMALLINT, + SEQTYPE_INTEGER, + SEQTYPE_BIGINT, +} SeqType; + +const char *const SeqTypeNames[] = +{ + [SEQTYPE_SMALLINT] = "smallint", + [SEQTYPE_INTEGER] = "integer", + [SEQTYPE_BIGINT] = "bigint", +}; + +StaticAssertDecl(lengthof(SeqTypeNames) == (SEQTYPE_BIGINT + 1), + "array length mismatch"); + typedef enum OidOptions { zeroIsError = 1, @@ -17251,6 +17269,19 @@ dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo) free(qtabname); } +static inline SeqType +parse_sequence_type(const char *name) +{ + for (int i = 0; i < lengthof(SeqTypeNames); i++) + { + if (strcmp(SeqTypeNames[i], name) == 0) + return (SeqType) i; + } + + pg_fatal("unrecognized sequence type: %s", name); + return (SeqType) 0; /* keep compiler quiet */ +} + /* * dumpSequence * write the declaration (not data) of one user-defined sequence @@ -17260,18 +17291,16 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) { DumpOptions *dopt = fout->dopt; PGresult *res; - char *startv, - *incby, - *maxv, - *minv, - *cache, - *seqtype; + SeqType seqtype; bool cycled; bool is_ascending; int64 default_minv, - default_maxv; - char bufm[32], - bufx[32]; + default_maxv, + minv, + maxv, + startv, + incby, + cache; PQExpBuffer query = createPQExpBuffer(); PQExpBuffer delqry = createPQExpBuffer(); char *qseqname; @@ -17313,50 +17342,39 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) PQntuples(res)), tbinfo->dobj.name, PQntuples(res)); - seqtype = PQgetvalue(res, 0, 0); - startv = PQgetvalue(res, 0, 1); - incby = PQgetvalue(res, 0, 2); - maxv = PQgetvalue(res, 0, 3); - minv = PQgetvalue(res, 0, 4); - cache = PQgetvalue(res, 0, 5); + seqtype = parse_sequence_type(PQgetvalue(res, 0, 0)); + startv = strtoi64(PQgetvalue(res, 0, 1), NULL, 10); + incby = strtoi64(PQgetvalue(res, 0, 2), NULL, 10); + maxv = strtoi64(PQgetvalue(res, 0, 3), NULL, 10); + minv = strtoi64(PQgetvalue(res, 0, 4), NULL, 10); + cache = strtoi64(PQgetvalue(res, 0, 5), NULL, 10); cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0); + PQclear(res); + /* Calculate default limits for a sequence of this type */ - is_ascending = (incby[0] != '-'); - if (strcmp(seqtype, "smallint") == 0) + is_ascending = (incby >= 0); + if (seqtype == SEQTYPE_SMALLINT) { default_minv = is_ascending ? 1 : PG_INT16_MIN; default_maxv = is_ascending ? PG_INT16_MAX : -1; } - else if (strcmp(seqtype, "integer") == 0) + else if (seqtype == SEQTYPE_INTEGER) { default_minv = is_ascending ? 1 : PG_INT32_MIN; default_maxv = is_ascending ? PG_INT32_MAX : -1; } - else if (strcmp(seqtype, "bigint") == 0) + else if (seqtype == SEQTYPE_BIGINT) { default_minv = is_ascending ? 1 : PG_INT64_MIN; default_maxv = is_ascending ? PG_INT64_MAX : -1; } else { - pg_fatal("unrecognized sequence type: %s", seqtype); + pg_fatal("unrecognized sequence type: %d", seqtype); default_minv = default_maxv = 0; /* keep compiler quiet */ } - /* - * 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); - - /* 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; - /* * Identity sequences are not to be dropped separately. */ @@ -17404,26 +17422,26 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) "UNLOGGED " : "", fmtQualifiedDumpable(tbinfo)); - if (strcmp(seqtype, "bigint") != 0) - appendPQExpBuffer(query, " AS %s\n", seqtype); + if (seqtype != SEQTYPE_BIGINT) + appendPQExpBuffer(query, " AS %s\n", SeqTypeNames[seqtype]); } - appendPQExpBuffer(query, " START WITH %s\n", startv); + appendPQExpBuffer(query, " START WITH " INT64_FORMAT "\n", startv); - appendPQExpBuffer(query, " INCREMENT BY %s\n", incby); + appendPQExpBuffer(query, " INCREMENT BY " INT64_FORMAT "\n", incby); - if (minv) - appendPQExpBuffer(query, " MINVALUE %s\n", minv); + if (minv != default_minv) + appendPQExpBuffer(query, " MINVALUE " INT64_FORMAT "\n", minv); else appendPQExpBufferStr(query, " NO MINVALUE\n"); - if (maxv) - appendPQExpBuffer(query, " MAXVALUE %s\n", maxv); + if (maxv != default_maxv) + appendPQExpBuffer(query, " MAXVALUE " INT64_FORMAT "\n", maxv); else appendPQExpBufferStr(query, " NO MAXVALUE\n"); appendPQExpBuffer(query, - " CACHE %s%s", + " CACHE " INT64_FORMAT "%s", cache, (cycled ? "\n CYCLE" : "")); if (tbinfo->is_identity_sequence) @@ -17510,8 +17528,6 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); - PQclear(res); - destroyPQExpBuffer(query); destroyPQExpBuffer(delqry); free(qseqname); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 3deb6113b80..343a8dae7da 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2572,6 +2572,7 @@ SeqScan SeqScanState SeqTable SeqTableData +SeqType SerCommitSeqNo SerialControl SerialIOData