1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * $PostgreSQL: pgsql/src/bin/scripts/vacuumdb.c,v 1.32 2010/01/07 12:38:55 momjian Exp $
10 *-------------------------------------------------------------------------
13 #include "postgres_fe.h"
17 static void vacuum_one_database(const char *dbname, bool full, bool inplace, bool verbose,
18 bool and_analyze, bool analyze_only, bool freeze,
19 const char *table, const char *host, const char *port,
20 const char *username, enum trivalue prompt_password,
21 const char *progname, bool echo);
22 static void vacuum_all_databases(bool full, bool inplace, bool verbose, bool and_analyze,
23 bool analyze_only, bool freeze,
24 const char *host, const char *port,
25 const char *username, enum trivalue prompt_password,
26 const char *progname, bool echo, bool quiet);
28 static void help(const char *progname);
32 main(int argc, char *argv[])
34 static struct option long_options[] = {
35 {"host", required_argument, NULL, 'h'},
36 {"port", required_argument, NULL, 'p'},
37 {"username", required_argument, NULL, 'U'},
38 {"no-password", no_argument, NULL, 'w'},
39 {"password", no_argument, NULL, 'W'},
40 {"echo", no_argument, NULL, 'e'},
41 {"quiet", no_argument, NULL, 'q'},
42 {"dbname", required_argument, NULL, 'd'},
43 {"analyze", no_argument, NULL, 'z'},
44 {"analyze-only", no_argument, NULL, 'o'},
45 {"freeze", no_argument, NULL, 'F'},
46 {"all", no_argument, NULL, 'a'},
47 {"table", required_argument, NULL, 't'},
48 {"full", no_argument, NULL, 'f'},
49 {"verbose", no_argument, NULL, 'v'},
50 {"inplace", no_argument, NULL, 'i'},
58 const char *dbname = NULL;
61 char *username = NULL;
62 enum trivalue prompt_password = TRI_DEFAULT;
65 bool and_analyze = false;
66 bool analyze_only = false;
74 progname = get_progname(argv[0]);
75 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
77 handle_help_version_opts(argc, argv, "vacuumdb", help);
79 while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zaFt:fiv", long_options, &optindex)) != -1)
93 prompt_password = TRI_NO;
96 prompt_password = TRI_YES;
132 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
137 switch (argc - optind)
142 dbname = argv[optind];
145 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
146 progname, argv[optind + 1]);
147 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
151 if (inplace && !full)
153 fprintf(stderr, _("%s: cannot use the \"inplace\" option when performing full vacuum\n"),
162 fprintf(stderr, _("%s: cannot use the \"full\" option when performing only analyze\n"),
168 fprintf(stderr, _("%s: cannot use the \"freeze\" option when performing only analyze\n"),
172 /* allow 'and_analyze' with 'analyze_only' */
175 setup_cancel_handler();
181 fprintf(stderr, _("%s: cannot vacuum all databases and a specific one at the same time\n"),
187 fprintf(stderr, _("%s: cannot vacuum a specific table in all databases\n"),
192 vacuum_all_databases(full, inplace, verbose, and_analyze, analyze_only, freeze,
193 host, port, username, prompt_password,
194 progname, echo, quiet);
200 if (getenv("PGDATABASE"))
201 dbname = getenv("PGDATABASE");
202 else if (getenv("PGUSER"))
203 dbname = getenv("PGUSER");
205 dbname = get_user_name(progname);
208 vacuum_one_database(dbname, full, inplace, verbose, and_analyze, analyze_only,
210 host, port, username, prompt_password,
219 vacuum_one_database(const char *dbname, bool full, bool inplace, bool verbose, bool and_analyze,
220 bool analyze_only, bool freeze, const char *table,
221 const char *host, const char *port,
222 const char *username, enum trivalue prompt_password,
223 const char *progname, bool echo)
229 initPQExpBuffer(&sql);
231 conn = connectDatabase(dbname, host, port, username, prompt_password, progname);
235 appendPQExpBuffer(&sql, "ANALYZE");
237 appendPQExpBuffer(&sql, " VERBOSE");
241 appendPQExpBuffer(&sql, "VACUUM");
242 if (PQserverVersion(conn) >= 80500)
244 const char *paren = " (";
245 const char *comma = ", ";
246 const char *sep = paren;
250 appendPQExpBuffer(&sql, "%sFULL%s", sep,
251 inplace ? " INPLACE" : "");
256 appendPQExpBuffer(&sql, "%sFREEZE", sep);
261 appendPQExpBuffer(&sql, "%sVERBOSE", sep);
266 appendPQExpBuffer(&sql, "%sANALYZE", sep);
270 appendPQExpBuffer(&sql, ")");
275 * On older servers, VACUUM FULL is equivalent to VACUUM (FULL
276 * INPLACE) on newer servers, so we can ignore 'inplace'.
279 appendPQExpBuffer(&sql, " FULL");
281 appendPQExpBuffer(&sql, " FREEZE");
283 appendPQExpBuffer(&sql, " VERBOSE");
285 appendPQExpBuffer(&sql, " ANALYZE");
289 appendPQExpBuffer(&sql, " %s", table);
290 appendPQExpBuffer(&sql, ";\n");
292 if (!executeMaintenanceCommand(conn, sql.data, echo))
295 fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
296 progname, table, dbname, PQerrorMessage(conn));
298 fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
299 progname, dbname, PQerrorMessage(conn));
304 termPQExpBuffer(&sql);
309 vacuum_all_databases(bool full, bool inplace, bool verbose, bool and_analyze, bool analyze_only,
310 bool freeze, const char *host, const char *port,
311 const char *username, enum trivalue prompt_password,
312 const char *progname, bool echo, bool quiet)
318 conn = connectDatabase("postgres", host, port, username, prompt_password, progname);
319 result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
322 for (i = 0; i < PQntuples(result); i++)
324 char *dbname = PQgetvalue(result, i, 0);
328 printf(_("%s: vacuuming database \"%s\"\n"), progname, dbname);
332 vacuum_one_database(dbname, full, inplace, verbose, and_analyze, analyze_only,
333 freeze, NULL, host, port, username, prompt_password,
342 help(const char *progname)
344 printf(_("%s cleans and analyzes a PostgreSQL database.\n\n"), progname);
345 printf(_("Usage:\n"));
346 printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
347 printf(_("\nOptions:\n"));
348 printf(_(" -a, --all vacuum all databases\n"));
349 printf(_(" -d, --dbname=DBNAME database to vacuum\n"));
350 printf(_(" -e, --echo show the commands being sent to the server\n"));
351 printf(_(" -f, --full do full vacuuming\n"));
352 printf(_(" -F, --freeze freeze row transaction information\n"));
353 printf(_(" -i, --inplace do full inplace vacuuming\n"));
354 printf(_(" -o, --analyze-only only update optimizer hints\n"));
355 printf(_(" -q, --quiet don't write any messages\n"));
356 printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n"));
357 printf(_(" -v, --verbose write a lot of output\n"));
358 printf(_(" -z, --analyze update optimizer hints\n"));
359 printf(_(" --help show this help, then exit\n"));
360 printf(_(" --version output version information, then exit\n"));
361 printf(_("\nConnection options:\n"));
362 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
363 printf(_(" -p, --port=PORT database server port\n"));
364 printf(_(" -U, --username=USERNAME user name to connect as\n"));
365 printf(_(" -w, --no-password never prompt for password\n"));
366 printf(_(" -W, --password force password prompt\n"));
367 printf(_("\nRead the description of the SQL command VACUUM for details.\n"));
368 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));