pgbench: Ensure previous progress message is fully cleared when updating.
authorFujii Masao <fujii@postgresql.org>
Wed, 27 Nov 2024 14:01:53 +0000 (23:01 +0900)
committerFujii Masao <fujii@postgresql.org>
Wed, 27 Nov 2024 14:01:53 +0000 (23:01 +0900)
During pgbench's table initialization, progress updates could display
leftover characters from the previous message if the new message
was shorter. This commit resolves the issue by appending spaces to
the current message to fully overwrite any remaining characters from
the previous line.

Back-patch to all the supported versions.

Author: Yushi Ogiwara, Tatsuo Ishii, Fujii Masao
Reviewed-by: Tatsuo Ishii, Fujii Masao
Discussion: https://postgr.es/m/9a9b8b95b6a709877ae48ad5b0c59bb9@oss.nttdata.com

src/bin/pgbench/pgbench.c

index ba247f3f85cfe26c3282d7742c546dfa11d4818f..85e7b68baa3787dd5e8c6f06ecf7d2aa38d40599 100644 (file)
@@ -4944,6 +4944,7 @@ initPopulateTable(PGconn *con, const char *table, int64 base,
    int         n;
    int64       k;
    int         chars = 0;
+   int         prev_chars = 0;
    PGresult   *res;
    PQExpBufferData sql;
    char        copy_statement[256];
@@ -5004,10 +5005,10 @@ initPopulateTable(PGconn *con, const char *table, int64 base,
            double      elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
            double      remaining_sec = ((double) total - j) * elapsed_sec / j;
 
-           chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)%c",
+           chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)",
                            j, total,
                            (int) ((j * 100) / total),
-                           table, elapsed_sec, remaining_sec, eol);
+                           table, elapsed_sec, remaining_sec);
        }
        /* let's not call the timing for each row, but only each 100 rows */
        else if (use_quiet && (j % 100 == 0))
@@ -5018,19 +5019,29 @@ initPopulateTable(PGconn *con, const char *table, int64 base,
            /* have we reached the next interval (or end)? */
            if ((j == total) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
            {
-               chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)%c",
+               chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)",
                                j, total,
                                (int) ((j * 100) / total),
-                               table, elapsed_sec, remaining_sec, eol);
+                               table, elapsed_sec, remaining_sec);
 
                /* skip to the next interval */
                log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
            }
        }
+
+       /*
+        * If the previous progress message is longer than the current one,
+        * add spaces to the current line to fully overwrite any remaining
+        * characters from the previous message.
+        */
+       if (prev_chars > chars)
+           fprintf(stderr, "%*c", prev_chars - chars, ' ');
+       fputc(eol, stderr);
+       prev_chars = chars;
    }
 
    if (chars != 0 && eol != '\n')
-       fprintf(stderr, "%*c\r", chars - 1, ' ');   /* Clear the current line */
+       fprintf(stderr, "%*c\r", chars, ' ');   /* Clear the current line */
 
    if (PQputline(con, "\\.\n"))
        pg_fatal("very last PQputline failed");