17#include "catalog/pg_class_d.h"
70 const char *
progname,
bool echo,
bool quiet);
74 bool analyze_in_stages,
77 const char *
progname,
bool echo,
bool quiet);
92#define ANALYZE_NO_STAGE -1
93#define ANALYZE_NUM_STAGES 3
97main(
int argc,
char *argv[])
99 static struct option long_options[] = {
137 const char *
dbname = NULL;
138 const char *maintenance_db = NULL;
147 bool analyze_in_stages =
false;
149 int concurrentCons = 1;
153 memset(&vacopts, 0,
sizeof(vacopts));
168 while ((
c =
getopt_long(argc, argv,
"ad:efFh:j:n:N:p:P:qt:U:vwWzZ", long_options, &optindex)) != -1)
298 pg_log_error(
"too many command-line arguments (first is \"%s\")",
313 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
316 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
319 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
320 "disable-page-skipping");
322 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
325 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
326 "force-index-cleanup");
328 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
331 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
334 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
343 pg_fatal(
"cannot use the \"%s\" option when performing only analyze",
346 pg_fatal(
"cannot use the \"%s\" option when performing full vacuum",
352 pg_fatal(
"cannot use the \"%s\" option with the \"%s\" option",
353 "no-index-cleanup",
"force-index-cleanup");
360 pg_fatal(
"cannot use the \"%s\" option with the \"%s\" option",
361 "buffer-usage-limit",
"full");
373 if (tbl_count && (concurrentCons > tbl_count))
374 concurrentCons = tbl_count;
378 cparams.
dbname = maintenance_db;
390 if (getenv(
"PGDATABASE"))
391 dbname = getenv(
"PGDATABASE");
392 else if (getenv(
"PGUSER"))
393 dbname = getenv(
"PGUSER");
400 if (analyze_in_stages)
432 pg_fatal(
"cannot vacuum all databases and a specific one at the same time");
436 pg_fatal(
"cannot vacuum all tables in schema(s) and specific table(s) at the same time");
440 pg_fatal(
"cannot vacuum specific table(s) and exclude schema(s) at the same time");
444 pg_fatal(
"cannot vacuum all tables in schema(s) and exclude schema(s) at the same time");
479 const char *
progname,
bool echo,
bool quiet)
492 bool objects_listed =
false;
494 const char *stage_commands[] = {
495 "SET default_statistics_target=1; SET vacuum_cost_delay=0;",
496 "SET default_statistics_target=10; RESET vacuum_cost_delay;",
497 "RESET default_statistics_target;"
499 const char *stage_messages[] = {
500 gettext_noop(
"Generating minimal optimizer statistics (1 target)"),
501 gettext_noop(
"Generating medium optimizer statistics (10 targets)"),
502 gettext_noop(
"Generating default (full) optimizer statistics")
513 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
514 "disable-page-skipping",
"9.6");
520 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
521 "no-index-cleanup",
"12");
527 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
528 "force-index-cleanup",
"12");
534 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
535 "no-truncate",
"12");
541 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
542 "no-process-main",
"16");
548 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
549 "no-process-toast",
"14");
555 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
556 "skip-locked",
"12");
560 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
561 "--min-xid-age",
"9.6");
564 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
565 "--min-mxid-age",
"9.6");
568 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
572 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
573 "--buffer-usage-limit",
"16");
581 printf(
_(
"%s: processing database \"%s\": %s\n"),
584 printf(
_(
"%s: vacuuming database \"%s\"\n"),
604 for (cell = objects ? objects->
head : NULL; cell; cell = cell->
next)
606 char *just_table = NULL;
607 const char *just_columns = NULL;
612 "WITH listed_objects (object_oid, column_list) "
614 objects_listed =
true;
634 &just_table, &just_columns);
640 if (just_columns && just_columns[0] !=
'\0')
660 " FROM pg_catalog.pg_class c\n"
661 " JOIN pg_catalog.pg_namespace ns"
662 " ON c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
663 " LEFT JOIN pg_catalog.pg_class t"
664 " ON c.reltoastrelid OPERATOR(pg_catalog.=) t.oid\n");
673 " ON listed_objects.object_oid"
674 " OPERATOR(pg_catalog.=) ");
686 " WHERE c.relpersistence OPERATOR(pg_catalog.!=) "
697 " AND listed_objects.object_oid IS NULL\n");
700 " AND listed_objects.object_oid IS NOT NULL\n");
712 " AND c.relkind OPERATOR(pg_catalog.=) ANY (array["
727 " AND GREATEST(pg_catalog.age(c.relfrozenxid),"
728 " pg_catalog.age(t.relfrozenxid)) "
729 " OPERATOR(pg_catalog.>=) '%d'::pg_catalog.int4\n"
730 " AND c.relfrozenxid OPERATOR(pg_catalog.!=)"
731 " '0'::pg_catalog.xid\n",
738 " AND GREATEST(pg_catalog.mxid_age(c.relminmxid),"
739 " pg_catalog.mxid_age(t.relminmxid)) OPERATOR(pg_catalog.>=)"
740 " '%d'::pg_catalog.int4\n"
741 " AND c.relminmxid OPERATOR(pg_catalog.!=)"
742 " '0'::pg_catalog.xid\n",
772 for (
i = 0;
i < ntups;
i++)
791 if (concurrentCons > ntups)
792 concurrentCons = ntups;
793 if (concurrentCons <= 0)
805 initcmd = stage_commands[stage];
819 cell = dbtables.
head;
822 const char *tabname = cell->
val;
850 }
while (cell != NULL);
861 const char *cmd =
"VACUUM (ONLY_DATABASE_STATS);";
897 bool analyze_in_stages,
900 const char *
progname,
bool echo,
bool quiet)
909 "SELECT datname FROM pg_database WHERE datallowconn AND datconnlimit <> -2 ORDER BY 1;",
913 if (analyze_in_stages)
965 const char *paren =
" (";
966 const char *
comma =
", ";
967 const char *sep = paren;
976 if (serverVersion >= 110000)
981 Assert(serverVersion >= 120000);
992 Assert(serverVersion >= 160000);
1011 if (serverVersion >= 90000)
1016 Assert(serverVersion >= 90600);
1023 Assert(serverVersion >= 120000);
1031 Assert(serverVersion >= 120000);
1039 Assert(serverVersion >= 120000);
1046 Assert(serverVersion >= 160000);
1053 Assert(serverVersion >= 140000);
1060 Assert(serverVersion >= 160000);
1067 Assert(serverVersion >= 120000);
1094 Assert(serverVersion >= 130000);
1101 Assert(serverVersion >= 160000);
1145 pg_log_error(
"vacuuming of table \"%s\" in database \"%s\" failed: %s",
1148 pg_log_error(
"vacuuming of database \"%s\" failed: %s",
1156 printf(
_(
"%s cleans and analyzes a PostgreSQL database.\n\n"),
progname);
1160 printf(
_(
" -a, --all vacuum all databases\n"));
1161 printf(
_(
" --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n"));
1162 printf(
_(
" -d, --dbname=DBNAME database to vacuum\n"));
1163 printf(
_(
" --disable-page-skipping disable all page-skipping behavior\n"));
1164 printf(
_(
" -e, --echo show the commands being sent to the server\n"));
1165 printf(
_(
" -f, --full do full vacuuming\n"));
1166 printf(
_(
" -F, --freeze freeze row transaction information\n"));
1167 printf(
_(
" --force-index-cleanup always remove index entries that point to dead tuples\n"));
1168 printf(
_(
" -j, --jobs=NUM use this many concurrent connections to vacuum\n"));
1169 printf(
_(
" --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n"));
1170 printf(
_(
" --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n"));
1171 printf(
_(
" --no-index-cleanup don't remove index entries that point to dead tuples\n"));
1172 printf(
_(
" --no-process-main skip the main relation\n"));
1173 printf(
_(
" --no-process-toast skip the TOAST table associated with the table to vacuum\n"));
1174 printf(
_(
" --no-truncate don't truncate empty pages at the end of the table\n"));
1175 printf(
_(
" -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n"));
1176 printf(
_(
" -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n"));
1177 printf(
_(
" -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n"));
1178 printf(
_(
" -q, --quiet don't write any messages\n"));
1179 printf(
_(
" --skip-locked skip relations that cannot be immediately locked\n"));
1180 printf(
_(
" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n"));
1181 printf(
_(
" -v, --verbose write a lot of output\n"));
1182 printf(
_(
" -V, --version output version information, then exit\n"));
1183 printf(
_(
" -z, --analyze update optimizer statistics\n"));
1184 printf(
_(
" -Z, --analyze-only only update optimizer statistics; no vacuum\n"));
1185 printf(
_(
" --analyze-in-stages only update optimizer statistics, in multiple\n"
1186 " stages for faster results; no vacuum\n"));
1187 printf(
_(
" -?, --help show this help, then exit\n"));
1188 printf(
_(
"\nConnection options:\n"));
1189 printf(
_(
" -h, --host=HOSTNAME database server host or socket directory\n"));
1190 printf(
_(
" -p, --port=PORT database server port\n"));
1191 printf(
_(
" -U, --username=USERNAME user name to connect as\n"));
1192 printf(
_(
" -w, --no-password never prompt for password\n"));
1193 printf(
_(
" -W, --password force password prompt\n"));
1194 printf(
_(
" --maintenance-db=DBNAME alternate maintenance database\n"));
1195 printf(
_(
"\nRead the description of the SQL command VACUUM for details.\n"));
1196 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1197 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns)
#define Assert(condition)
#define PG_TEXTDOMAIN(domain)
volatile sig_atomic_t CancelRequested
void setup_cancel_handler(void(*query_cancel_callback)(void))
void set_pglocale_pgservice(const char *argv0, const char *app)
#define ALWAYS_SECURE_SEARCH_PATH_SQL
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
static void PGresult * res
int PQserverVersion(const PGconn *conn)
char * PQdb(const PGconn *conn)
int PQclientEncoding(const PGconn *conn)
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQntuples(const PGresult *res)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQsendQuery(PGconn *conn, const char *query)
char * pg_strdup(const char *in)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
static void const char fflush(stdout)
void pg_logging_init(const char *argv0)
#define pg_log_error(...)
#define pg_log_error_hint(...)
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
bool TableCommandResultHandler(PGresult *res, PGconn *conn, void *context)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
void ParallelSlotsTerminate(ParallelSlotArray *sa)
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
static PGconn * connectDatabase(const char *dbname, const char *connection_string, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error)
static void executeCommand(PGconn *conn, const char *query)
static PGresult * executeQuery(PGconn *conn, const char *query)
PGDLLIMPORT char * optarg
char * escape_single_quotes_ascii(const char *src)
const char * get_progname(const char *argv0)
void initPQExpBuffer(PQExpBuffer str)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
void simple_string_list_append(SimpleStringList *list, const char *val)
const char * fmtQualifiedId(const char *schema, const char *id)
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
char val[FLEXIBLE_ARRAY_MEMBER]
struct SimpleStringListCell * next
SimpleStringListCell * head
enum trivalue prompt_password
bool disable_page_skipping
char * buffer_usage_limit
const char * get_user_name_or_exit(const char *progname)
int main(int argc, char *argv[])
void check_objfilter(void)
static void vacuum_all_databases(ConnParams *cparams, vacuumingOptions *vacopts, bool analyze_in_stages, SimpleStringList *objects, int concurrentCons, const char *progname, bool echo, bool quiet)
static void help(const char *progname)
struct vacuumingOptions vacuumingOptions
static void run_vacuum_command(PGconn *conn, const char *sql, bool echo, const char *table)
#define ANALYZE_NUM_STAGES
@ OBJFILTER_SCHEMA_EXCLUDE
static void prepare_vacuum_command(PQExpBuffer sql, int serverVersion, vacuumingOptions *vacopts, const char *table)
static char * escape_quotes(const char *src)
static void vacuum_one_database(ConnParams *cparams, vacuumingOptions *vacopts, int stage, SimpleStringList *objects, int concurrentCons, const char *progname, bool echo, bool quiet)
static VacObjFilter objfilter