Parse sequence type and integer metadata in dumpSequence().
authorNathan Bossart <[email protected]>
Wed, 31 Jul 2024 15:12:41 +0000 (10:12 -0500)
committerNathan Bossart <[email protected]>
Wed, 31 Jul 2024 15:12:41 +0000 (10:12 -0500)
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
src/tools/pgindent/typedefs.list

index 2b02148559b95bb42dc11becd0640ed20efe4610..9c463137c051a84bdd12603d7f3b0b7e20395abf 100644 (file)
@@ -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);
index 3deb6113b80abf2b2452b2e69edf70974a06aa07..343a8dae7dae7b85fc7731359230101197e9ba20 100644 (file)
@@ -2572,6 +2572,7 @@ SeqScan
 SeqScanState
 SeqTable
 SeqTableData
+SeqType
 SerCommitSeqNo
 SerialControl
 SerialIOData