Fix vacuumdb to pass buffer-usage-limit with analyze-only mode
authorDavid Rowley <drowley@postgresql.org>
Thu, 21 Sep 2023 05:47:20 +0000 (17:47 +1200)
committerDavid Rowley <drowley@postgresql.org>
Thu, 21 Sep 2023 05:47:20 +0000 (17:47 +1200)
ae78cae3b added the --buffer-usage-limit to vacuumdb to allow it to
include the BUFFER_USAGE_LIMIT option in the VACUUM command.
Unfortunately, that commit forgot to adjust the code so the option was
added to the ANALYZE command when the -Z command line argument was
specified.

There were no issues with the -z command as that option just adds
ANALYZE to the VACUUM command.

In passing adjust the code to escape the --buffer-usage-limit option
before passing it to the server.  It seems nothing beyond a confusing
error message could become this lack of escaping as VACUUM cannot be
specified in a multi-command string.

Reported-by: Ryoga Yoshida
Author: Ryoga Yoshida, David Rowley
Discussion: https://postgr.es/m/08930c0b541700a5264e5fbf3a685f5a%40oss.nttdata.com
Backpatch-through: 16, where ae78cae3b was introduced.

src/bin/scripts/vacuumdb.c

index f03d5b1c6cbf233d21ad9e87635b40f26b081716..005b064c06cd16768eafbed070cfc0250a9b5260 100644 (file)
@@ -85,6 +85,8 @@ static void help(const char *progname);
 
 void           check_objfilter(void);
 
+static char *escape_quotes(const char *src);
+
 /* For analyze-in-stages mode */
 #define ANALYZE_NO_STAGE       -1
 #define ANALYZE_NUM_STAGES     3
@@ -270,7 +272,7 @@ main(int argc, char *argv[])
                                vacopts.process_main = false;
                                break;
                        case 13:
-                               vacopts.buffer_usage_limit = pg_strdup(optarg);
+                               vacopts.buffer_usage_limit = escape_quotes(optarg);
                                break;
                        default:
                                /* getopt_long already emitted a complaint */
@@ -452,6 +454,20 @@ check_objfilter(void)
                pg_fatal("cannot vacuum all tables in schema(s) and exclude schema(s) at the same time");
 }
 
+/*
+ * Returns a newly malloc'd version of 'src' with escaped single quotes and
+ * backslashes.
+ */
+static char *
+escape_quotes(const char *src)
+{
+       char       *result = escape_single_quotes_ascii(src);
+
+       if (!result)
+               pg_fatal("out of memory");
+       return result;
+}
+
 /*
  * vacuum_one_database
  *
@@ -964,6 +980,13 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
                                appendPQExpBuffer(sql, "%sVERBOSE", sep);
                                sep = comma;
                        }
+                       if (vacopts->buffer_usage_limit)
+                       {
+                               Assert(serverVersion >= 160000);
+                               appendPQExpBuffer(sql, "%sBUFFER_USAGE_LIMIT '%s'", sep,
+                                                                 vacopts->buffer_usage_limit);
+                               sep = comma;
+                       }
                        if (sep != paren)
                                appendPQExpBufferChar(sql, ')');
                }