00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "postgres_fe.h"
00014 #include "common.h"
00015 #include "dumputils.h"
00016
00017
00018 static void vacuum_one_database(const char *dbname, bool full, bool verbose,
00019 bool and_analyze, bool analyze_only, bool freeze,
00020 const char *table, const char *host, const char *port,
00021 const char *username, enum trivalue prompt_password,
00022 const char *progname, bool echo);
00023 static void vacuum_all_databases(bool full, bool verbose, bool and_analyze,
00024 bool analyze_only, bool freeze,
00025 const char *maintenance_db,
00026 const char *host, const char *port,
00027 const char *username, enum trivalue prompt_password,
00028 const char *progname, bool echo, bool quiet);
00029
00030 static void help(const char *progname);
00031
00032
00033 int
00034 main(int argc, char *argv[])
00035 {
00036 static struct option long_options[] = {
00037 {"host", required_argument, NULL, 'h'},
00038 {"port", required_argument, NULL, 'p'},
00039 {"username", required_argument, NULL, 'U'},
00040 {"no-password", no_argument, NULL, 'w'},
00041 {"password", no_argument, NULL, 'W'},
00042 {"echo", no_argument, NULL, 'e'},
00043 {"quiet", no_argument, NULL, 'q'},
00044 {"dbname", required_argument, NULL, 'd'},
00045 {"analyze", no_argument, NULL, 'z'},
00046 {"analyze-only", no_argument, NULL, 'Z'},
00047 {"freeze", no_argument, NULL, 'F'},
00048 {"all", no_argument, NULL, 'a'},
00049 {"table", required_argument, NULL, 't'},
00050 {"full", no_argument, NULL, 'f'},
00051 {"verbose", no_argument, NULL, 'v'},
00052 {"maintenance-db", required_argument, NULL, 2},
00053 {NULL, 0, NULL, 0}
00054 };
00055
00056 const char *progname;
00057 int optindex;
00058 int c;
00059
00060 const char *dbname = NULL;
00061 const char *maintenance_db = NULL;
00062 char *host = NULL;
00063 char *port = NULL;
00064 char *username = NULL;
00065 enum trivalue prompt_password = TRI_DEFAULT;
00066 bool echo = false;
00067 bool quiet = false;
00068 bool and_analyze = false;
00069 bool analyze_only = false;
00070 bool freeze = false;
00071 bool alldb = false;
00072 bool full = false;
00073 bool verbose = false;
00074 SimpleStringList tables = {NULL, NULL};
00075
00076 progname = get_progname(argv[0]);
00077 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
00078
00079 handle_help_version_opts(argc, argv, "vacuumdb", help);
00080
00081 while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zZFat:fv", long_options, &optindex)) != -1)
00082 {
00083 switch (c)
00084 {
00085 case 'h':
00086 host = pg_strdup(optarg);
00087 break;
00088 case 'p':
00089 port = pg_strdup(optarg);
00090 break;
00091 case 'U':
00092 username = pg_strdup(optarg);
00093 break;
00094 case 'w':
00095 prompt_password = TRI_NO;
00096 break;
00097 case 'W':
00098 prompt_password = TRI_YES;
00099 break;
00100 case 'e':
00101 echo = true;
00102 break;
00103 case 'q':
00104 quiet = true;
00105 break;
00106 case 'd':
00107 dbname = pg_strdup(optarg);
00108 break;
00109 case 'z':
00110 and_analyze = true;
00111 break;
00112 case 'Z':
00113 analyze_only = true;
00114 break;
00115 case 'F':
00116 freeze = true;
00117 break;
00118 case 'a':
00119 alldb = true;
00120 break;
00121 case 't':
00122 simple_string_list_append(&tables, optarg);
00123 break;
00124 case 'f':
00125 full = true;
00126 break;
00127 case 'v':
00128 verbose = true;
00129 break;
00130 case 2:
00131 maintenance_db = pg_strdup(optarg);
00132 break;
00133 default:
00134 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00135 exit(1);
00136 }
00137 }
00138
00139
00140
00141
00142
00143
00144 if (optind < argc && dbname == NULL)
00145 {
00146 dbname = argv[optind];
00147 optind++;
00148 }
00149
00150 if (optind < argc)
00151 {
00152 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
00153 progname, argv[optind]);
00154 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00155 exit(1);
00156 }
00157
00158 if (analyze_only)
00159 {
00160 if (full)
00161 {
00162 fprintf(stderr, _("%s: cannot use the \"full\" option when performing only analyze\n"),
00163 progname);
00164 exit(1);
00165 }
00166 if (freeze)
00167 {
00168 fprintf(stderr, _("%s: cannot use the \"freeze\" option when performing only analyze\n"),
00169 progname);
00170 exit(1);
00171 }
00172
00173 }
00174
00175 setup_cancel_handler();
00176
00177 if (alldb)
00178 {
00179 if (dbname)
00180 {
00181 fprintf(stderr, _("%s: cannot vacuum all databases and a specific one at the same time\n"),
00182 progname);
00183 exit(1);
00184 }
00185 if (tables.head != NULL)
00186 {
00187 fprintf(stderr, _("%s: cannot vacuum specific table(s) in all databases\n"),
00188 progname);
00189 exit(1);
00190 }
00191
00192 vacuum_all_databases(full, verbose, and_analyze, analyze_only, freeze,
00193 maintenance_db, host, port, username,
00194 prompt_password, progname, echo, quiet);
00195 }
00196 else
00197 {
00198 if (dbname == NULL)
00199 {
00200 if (getenv("PGDATABASE"))
00201 dbname = getenv("PGDATABASE");
00202 else if (getenv("PGUSER"))
00203 dbname = getenv("PGUSER");
00204 else
00205 dbname = get_user_name(progname);
00206 }
00207
00208 if (tables.head != NULL)
00209 {
00210 SimpleStringListCell *cell;
00211
00212 for (cell = tables.head; cell; cell = cell->next)
00213 {
00214 vacuum_one_database(dbname, full, verbose, and_analyze,
00215 analyze_only,
00216 freeze, cell->val,
00217 host, port, username, prompt_password,
00218 progname, echo);
00219 }
00220 }
00221 else
00222 vacuum_one_database(dbname, full, verbose, and_analyze,
00223 analyze_only,
00224 freeze, NULL,
00225 host, port, username, prompt_password,
00226 progname, echo);
00227 }
00228
00229 exit(0);
00230 }
00231
00232
00233 static void
00234 vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyze,
00235 bool analyze_only, bool freeze, const char *table,
00236 const char *host, const char *port,
00237 const char *username, enum trivalue prompt_password,
00238 const char *progname, bool echo)
00239 {
00240 PQExpBufferData sql;
00241
00242 PGconn *conn;
00243
00244 initPQExpBuffer(&sql);
00245
00246 conn = connectDatabase(dbname, host, port, username, prompt_password,
00247 progname, false);
00248
00249 if (analyze_only)
00250 {
00251 appendPQExpBuffer(&sql, "ANALYZE");
00252 if (verbose)
00253 appendPQExpBuffer(&sql, " VERBOSE");
00254 }
00255 else
00256 {
00257 appendPQExpBuffer(&sql, "VACUUM");
00258 if (PQserverVersion(conn) >= 90000)
00259 {
00260 const char *paren = " (";
00261 const char *comma = ", ";
00262 const char *sep = paren;
00263
00264 if (full)
00265 {
00266 appendPQExpBuffer(&sql, "%sFULL", sep);
00267 sep = comma;
00268 }
00269 if (freeze)
00270 {
00271 appendPQExpBuffer(&sql, "%sFREEZE", sep);
00272 sep = comma;
00273 }
00274 if (verbose)
00275 {
00276 appendPQExpBuffer(&sql, "%sVERBOSE", sep);
00277 sep = comma;
00278 }
00279 if (and_analyze)
00280 {
00281 appendPQExpBuffer(&sql, "%sANALYZE", sep);
00282 sep = comma;
00283 }
00284 if (sep != paren)
00285 appendPQExpBuffer(&sql, ")");
00286 }
00287 else
00288 {
00289 if (full)
00290 appendPQExpBuffer(&sql, " FULL");
00291 if (freeze)
00292 appendPQExpBuffer(&sql, " FREEZE");
00293 if (verbose)
00294 appendPQExpBuffer(&sql, " VERBOSE");
00295 if (and_analyze)
00296 appendPQExpBuffer(&sql, " ANALYZE");
00297 }
00298 }
00299 if (table)
00300 appendPQExpBuffer(&sql, " %s", table);
00301 appendPQExpBuffer(&sql, ";\n");
00302
00303 if (!executeMaintenanceCommand(conn, sql.data, echo))
00304 {
00305 if (table)
00306 fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
00307 progname, table, dbname, PQerrorMessage(conn));
00308 else
00309 fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
00310 progname, dbname, PQerrorMessage(conn));
00311 PQfinish(conn);
00312 exit(1);
00313 }
00314 PQfinish(conn);
00315 termPQExpBuffer(&sql);
00316 }
00317
00318
00319 static void
00320 vacuum_all_databases(bool full, bool verbose, bool and_analyze, bool analyze_only,
00321 bool freeze, const char *maintenance_db,
00322 const char *host, const char *port,
00323 const char *username, enum trivalue prompt_password,
00324 const char *progname, bool echo, bool quiet)
00325 {
00326 PGconn *conn;
00327 PGresult *result;
00328 int i;
00329
00330 conn = connectMaintenanceDatabase(maintenance_db, host, port,
00331 username, prompt_password, progname);
00332 result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
00333 PQfinish(conn);
00334
00335 for (i = 0; i < PQntuples(result); i++)
00336 {
00337 char *dbname = PQgetvalue(result, i, 0);
00338
00339 if (!quiet)
00340 {
00341 printf(_("%s: vacuuming database \"%s\"\n"), progname, dbname);
00342 fflush(stdout);
00343 }
00344
00345 vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
00346 freeze, NULL, host, port, username, prompt_password,
00347 progname, echo);
00348 }
00349
00350 PQclear(result);
00351 }
00352
00353
00354 static void
00355 help(const char *progname)
00356 {
00357 printf(_("%s cleans and analyzes a PostgreSQL database.\n\n"), progname);
00358 printf(_("Usage:\n"));
00359 printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
00360 printf(_("\nOptions:\n"));
00361 printf(_(" -a, --all vacuum all databases\n"));
00362 printf(_(" -d, --dbname=DBNAME database to vacuum\n"));
00363 printf(_(" -e, --echo show the commands being sent to the server\n"));
00364 printf(_(" -f, --full do full vacuuming\n"));
00365 printf(_(" -F, --freeze freeze row transaction information\n"));
00366 printf(_(" -q, --quiet don't write any messages\n"));
00367 printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n"));
00368 printf(_(" -v, --verbose write a lot of output\n"));
00369 printf(_(" -V, --version output version information, then exit\n"));
00370 printf(_(" -z, --analyze update optimizer statistics\n"));
00371 printf(_(" -Z, --analyze-only only update optimizer statistics\n"));
00372 printf(_(" -?, --help show this help, then exit\n"));
00373 printf(_("\nConnection options:\n"));
00374 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
00375 printf(_(" -p, --port=PORT database server port\n"));
00376 printf(_(" -U, --username=USERNAME user name to connect as\n"));
00377 printf(_(" -w, --no-password never prompt for password\n"));
00378 printf(_(" -W, --password force password prompt\n"));
00379 printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
00380 printf(_("\nRead the description of the SQL command VACUUM for details.\n"));
00381 printf(_("\nReport bugs to <[email protected]>.\n"));
00382 }