From ef57a713580feb5f84f23882e6980cc31e74cf85 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 25 Sep 2024 14:45:01 +0900 Subject: [PATCH] vacuumdb: Skip temporary tables in query to build list of relations Running vacuumdb with a non-superuser while another user has created a temporary table would lead to a mid-flight permission failure, interrupting the operation. vacuum_rel() skips temporary relations of other backends, and it makes no sense for vacuumdb to know about these relations, so let's switch it to ignore temporary relations entirely. Adding a qual in the query based on relpersistence simplifies the generation of its WHERE clause in vacuum_one_database(), per se the removal of "has_where". Author: VaibhaveS, Michael Paquier Reviewed-by: Fujii Masao Discussion: https://postgr.es/m/CAM_eQjwfAR=y3G1fGyS1U9FTmc+FyJm9amNfY2QCZBnDDbNPZg@mail.gmail.com Backpatch-through: 12 --- src/bin/scripts/vacuumdb.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c index 97ec3ad0e99..151580ec449 100644 --- a/src/bin/scripts/vacuumdb.c +++ b/src/bin/scripts/vacuumdb.c @@ -390,7 +390,6 @@ vacuum_one_database(const ConnParams *cparams, bool failed = false; bool parallel = concurrentCons > 1; bool tables_listed = false; - bool has_where = false; const char *stage_commands[] = { "SET default_statistics_target=1; SET vacuum_cost_delay=0;", "SET default_statistics_target=10; RESET vacuum_cost_delay;", @@ -515,11 +514,21 @@ vacuum_one_database(const ConnParams *cparams, " LEFT JOIN pg_catalog.pg_class t" " ON c.reltoastrelid OPERATOR(pg_catalog.=) t.oid\n"); - /* Used to match the tables listed by the user */ + /* + * Used to match the tables listed by the user, completing the JOIN + * clause. + */ if (tables_listed) appendPQExpBuffer(&catalog_query, " JOIN listed_tables" " ON listed_tables.table_oid OPERATOR(pg_catalog.=) c.oid\n"); + /* + * Exclude temporary tables, beginning the WHERE clause. + */ + appendPQExpBufferStr(&catalog_query, + " WHERE c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)); + + /* * If no tables were listed, filter for the relevant relation types. If * tables were given via --table, don't bother filtering by relation type. @@ -528,10 +537,9 @@ vacuum_one_database(const ConnParams *cparams, */ if (!tables_listed) { - appendPQExpBuffer(&catalog_query, " WHERE c.relkind OPERATOR(pg_catalog.=) ANY (array[" + appendPQExpBuffer(&catalog_query, " AND c.relkind OPERATOR(pg_catalog.=) ANY (array[" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_MATVIEW) "])\n"); - has_where = true; } /* @@ -544,25 +552,23 @@ vacuum_one_database(const ConnParams *cparams, if (vacopts->min_xid_age != 0) { appendPQExpBuffer(&catalog_query, - " %s GREATEST(pg_catalog.age(c.relfrozenxid)," + " AND GREATEST(pg_catalog.age(c.relfrozenxid)," " pg_catalog.age(t.relfrozenxid)) " " OPERATOR(pg_catalog.>=) '%d'::pg_catalog.int4\n" " AND c.relfrozenxid OPERATOR(pg_catalog.!=)" " '0'::pg_catalog.xid\n", - has_where ? "AND" : "WHERE", vacopts->min_xid_age); - has_where = true; + vacopts->min_xid_age); } if (vacopts->min_mxid_age != 0) { appendPQExpBuffer(&catalog_query, - " %s GREATEST(pg_catalog.mxid_age(c.relminmxid)," + " AND GREATEST(pg_catalog.mxid_age(c.relminmxid)," " pg_catalog.mxid_age(t.relminmxid)) OPERATOR(pg_catalog.>=)" " '%d'::pg_catalog.int4\n" " AND c.relminmxid OPERATOR(pg_catalog.!=)" " '0'::pg_catalog.xid\n", - has_where ? "AND" : "WHERE", vacopts->min_mxid_age); - has_where = true; + vacopts->min_mxid_age); } /* -- 2.39.5