15#include "catalog/pg_attribute_d.h"
16#include "catalog/pg_class_d.h"
58 unsigned int tbl_count,
int concurrentCons,
64 if (tbl_count > 0 && (concurrentCons > tbl_count))
65 concurrentCons = tbl_count;
69 cparams->
dbname = maintenance_db;
80 if (getenv(
"PGDATABASE"))
81 dbname = getenv(
"PGDATABASE");
82 else if (getenv(
"PGUSER"))
179 bool free_retobjs =
false;
181 const char *stage_commands[] = {
182 "SET default_statistics_target=1; SET vacuum_cost_delay=0;",
183 "SET default_statistics_target=10; RESET vacuum_cost_delay;",
184 "RESET default_statistics_target;"
186 const char *stage_messages[] = {
187 gettext_noop(
"Generating minimal optimizer statistics (1 target)"),
188 gettext_noop(
"Generating medium optimizer statistics (10 targets)"),
189 gettext_noop(
"Generating default (full) optimizer statistics")
200 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
201 "disable-page-skipping",
"9.6");
207 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
208 "no-index-cleanup",
"12");
214 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
215 "force-index-cleanup",
"12");
221 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
222 "no-truncate",
"12");
228 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
229 "no-process-main",
"16");
235 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
236 "no-process-toast",
"14");
242 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
243 "skip-locked",
"12");
249 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
250 "--min-xid-age",
"9.6");
256 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
257 "--min-mxid-age",
"9.6");
263 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
270 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
271 "--buffer-usage-limit",
"16");
277 pg_fatal(
"cannot use the \"%s\" option on server versions older than PostgreSQL %s",
278 "--missing-stats-only",
"15");
287 printf(
_(
"%s: processing database \"%s\": %s\n"),
290 printf(
_(
"%s: vacuuming database \"%s\"\n"),
301 if (found_objs && *found_objs)
302 retobjs = *found_objs;
307 *found_objs = retobjs;
316 for (cell = retobjs->
head; cell; cell = cell->
next)
331 if (concurrentCons > ntups)
332 concurrentCons = ntups;
333 if (concurrentCons <= 0)
343 initcmd = stage_commands[stage];
359 vacopts->
echo, initcmd);
364 cell = retobjs->
head;
367 const char *tabname = cell->
val;
394 }
while (cell != NULL);
405 const char *cmd =
"VACUUM (ONLY_DATABASE_STATS);";
452 "SELECT datname FROM pg_database WHERE datallowconn AND datconnlimit <> -2 ORDER BY 1;",
474 for (
int i = 0;
i < numdbs;
i++)
491 for (
int i = 0;
i < numdbs;
i++)
498 for (
int i = 0;
i < numdbs;
i++)
538 bool objects_listed =
false;
541 for (cell = objects ? objects->
head : NULL; cell; cell = cell->
next)
543 char *just_table = NULL;
544 const char *just_columns = NULL;
549 "WITH listed_objects (object_oid, column_list) AS (\n"
551 objects_listed =
true;
571 &just_table, &just_columns);
577 if (just_columns && just_columns[0] !=
'\0')
597 " FROM pg_catalog.pg_class c\n"
598 " JOIN pg_catalog.pg_namespace ns"
599 " ON c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
600 " CROSS JOIN LATERAL (SELECT c.relkind IN ("
602 CppAsString2(RELKIND_PARTITIONED_INDEX)
")) as p (inherited)\n"
603 " LEFT JOIN pg_catalog.pg_class t"
604 " ON c.reltoastrelid OPERATOR(pg_catalog.=) t.oid\n");
613 " ON listed_objects.object_oid"
614 " OPERATOR(pg_catalog.=) ");
626 " WHERE c.relpersistence OPERATOR(pg_catalog.!=) "
637 " AND listed_objects.object_oid IS NULL\n");
640 " AND listed_objects.object_oid IS NOT NULL\n");
661 " AND c.relkind OPERATOR(pg_catalog.=) ANY (array["
667 " AND c.relkind OPERATOR(pg_catalog.=) ANY (array["
682 " AND GREATEST(pg_catalog.age(c.relfrozenxid),"
683 " pg_catalog.age(t.relfrozenxid)) "
684 " OPERATOR(pg_catalog.>=) '%d'::pg_catalog.int4\n"
685 " AND c.relfrozenxid OPERATOR(pg_catalog.!=)"
686 " '0'::pg_catalog.xid\n",
693 " AND GREATEST(pg_catalog.mxid_age(c.relminmxid),"
694 " pg_catalog.mxid_age(t.relminmxid)) OPERATOR(pg_catalog.>=)"
695 " '%d'::pg_catalog.int4\n"
696 " AND c.relminmxid OPERATOR(pg_catalog.!=)"
697 " '0'::pg_catalog.xid\n",
707 " EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n"
708 " WHERE a.attrelid OPERATOR(pg_catalog.=) c.oid\n"
709 " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n"
710 " AND NOT a.attisdropped\n"
711 " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n"
712 " AND a.attgenerated OPERATOR(pg_catalog.<>) "
714 " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n"
715 " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n"
716 " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n"
717 " AND s.stainherit OPERATOR(pg_catalog.=) p.inherited))\n");
721 " OR EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext e\n"
722 " WHERE e.stxrelid OPERATOR(pg_catalog.=) c.oid\n"
723 " AND e.stxstattarget IS DISTINCT FROM 0::pg_catalog.int2\n"
724 " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext_data d\n"
725 " WHERE d.stxoid OPERATOR(pg_catalog.=) e.oid\n"
726 " AND d.stxdinherit OPERATOR(pg_catalog.=) p.inherited))\n");
730 " OR EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n"
731 " JOIN pg_catalog.pg_index i"
732 " ON i.indexrelid OPERATOR(pg_catalog.=) a.attrelid\n"
733 " WHERE i.indrelid OPERATOR(pg_catalog.=) c.oid\n"
734 " AND i.indkey[a.attnum OPERATOR(pg_catalog.-) 1::pg_catalog.int2]"
735 " OPERATOR(pg_catalog.=) 0::pg_catalog.int2\n"
736 " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n"
737 " AND NOT a.attisdropped\n"
738 " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n"
739 " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n"
740 " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n"
741 " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n"
742 " AND s.stainherit OPERATOR(pg_catalog.=) p.inherited))\n");
746 " OR EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n"
747 " WHERE a.attrelid OPERATOR(pg_catalog.=) c.oid\n"
748 " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n"
749 " AND NOT a.attisdropped\n"
750 " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n"
751 " AND a.attgenerated OPERATOR(pg_catalog.<>) "
753 " AND c.relhassubclass\n"
754 " AND NOT p.inherited\n"
755 " AND EXISTS (SELECT NULL FROM pg_catalog.pg_inherits h\n"
756 " WHERE h.inhparent OPERATOR(pg_catalog.=) c.oid)\n"
757 " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n"
758 " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n"
759 " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n"
760 " AND s.stainherit))\n");
764 " OR EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext e\n"
765 " WHERE e.stxrelid OPERATOR(pg_catalog.=) c.oid\n"
766 " AND e.stxstattarget IS DISTINCT FROM 0::pg_catalog.int2\n"
767 " AND c.relhassubclass\n"
768 " AND NOT p.inherited\n"
769 " AND EXISTS (SELECT NULL FROM pg_catalog.pg_inherits h\n"
770 " WHERE h.inhparent OPERATOR(pg_catalog.=) c.oid)\n"
771 " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext_data d\n"
772 " WHERE d.stxoid OPERATOR(pg_catalog.=) e.oid\n"
773 " AND d.stxdinherit))\n");
840 const char *paren =
" (";
841 const char *
comma =
", ";
842 const char *sep = paren;
852 if (serverVersion >= 110000)
857 Assert(serverVersion >= 120000);
868 Assert(serverVersion >= 160000);
887 if (serverVersion >= 90000)
892 Assert(serverVersion >= 90600);
899 Assert(serverVersion >= 120000);
907 Assert(serverVersion >= 120000);
915 Assert(serverVersion >= 120000);
922 Assert(serverVersion >= 160000);
929 Assert(serverVersion >= 140000);
936 Assert(serverVersion >= 160000);
943 Assert(serverVersion >= 120000);
970 Assert(serverVersion >= 130000);
977 Assert(serverVersion >= 160000);
1010 const char *sql,
const char *
table)
1027 pg_log_error(
"vacuuming of table \"%s\" in database \"%s\" failed: %s",
1032 pg_log_error(
"vacuuming of database \"%s\" failed: %s",
void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns)
volatile sig_atomic_t CancelRequested
void setup_cancel_handler(void(*query_cancel_callback)(void))
#define ALWAYS_SECURE_SEARCH_PATH_SQL
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
PGconn * connectDatabase(const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
PGresult * executeQuery(PGconn *conn, const char *query)
int PQserverVersion(const PGconn *conn)
char * PQdb(const PGconn *conn)
int PQclientEncoding(const PGconn *conn)
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
int PQsendQuery(PGconn *conn, const char *query)
#define palloc0_object(type)
Assert(PointerIsAligned(start, uint64))
#define pg_log_error(...)
void * palloc0(Size size)
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 void ParallelSlotSetIdle(ParallelSlot *slot)
static void executeCommand(PGconn *conn, const char *query)
static const struct lconv_member_info table[]
static char buf[DEFAULT_XLOG_SEG_SIZE]
char * escape_single_quotes_ascii(const char *src)
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)
void simple_string_list_destroy(SimpleStringList *list)
const char * fmtQualifiedIdEnc(const char *schema, const char *id, int encoding)
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
char val[FLEXIBLE_ARRAY_MEMBER]
struct SimpleStringListCell * next
SimpleStringListCell * head
bool disable_page_skipping
char * buffer_usage_limit
const char * get_user_name_or_exit(const char *progname)
static void prepare_vacuum_command(PGconn *conn, PQExpBuffer sql, vacuumingOptions *vacopts, const char *table)
static int vacuum_all_databases(ConnParams *cparams, vacuumingOptions *vacopts, SimpleStringList *objects, int concurrentCons, const char *progname)
static int vacuum_one_database(ConnParams *cparams, vacuumingOptions *vacopts, int stage, SimpleStringList *objects, SimpleStringList **found_objs, int concurrentCons, const char *progname)
static void free_retrieved_objects(SimpleStringList *list)
static SimpleStringList * retrieve_objects(PGconn *conn, vacuumingOptions *vacopts, SimpleStringList *objects)
int vacuuming_main(ConnParams *cparams, const char *dbname, const char *maintenance_db, vacuumingOptions *vacopts, SimpleStringList *objects, unsigned int tbl_count, int concurrentCons, const char *progname)
char * escape_quotes(const char *src)
static void run_vacuum_command(ParallelSlot *free_slot, vacuumingOptions *vacopts, const char *sql, const char *table)
#define OBJFILTER_ALL_DBS
#define ANALYZE_NUM_STAGES
#define OBJFILTER_SCHEMA_EXCLUDE