aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/vacuum.c39
-rw-r--r--src/backend/parser/gram.y2
-rw-r--r--src/test/regress/expected/vacuum.out92
-rw-r--r--src/test/regress/sql/vacuum.sql66
4 files changed, 186 insertions, 13 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 7d8e9d20454..23aabdc90dc 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -851,7 +851,7 @@ vacuum_open_relation(Oid relid, RangeVar *relation, bits32 options,
/*
* Given a VacuumRelation, fill in the table OID if it wasn't specified,
- * and optionally add VacuumRelations for partitions of the table.
+ * and optionally add VacuumRelations for partitions or inheritance children.
*
* If a VacuumRelation does not have an OID supplied and is a partitioned
* table, an extra entry will be added to the output for each partition.
@@ -879,11 +879,15 @@ expand_vacuum_rel(VacuumRelation *vrel, MemoryContext vac_context,
}
else
{
- /* Process a specific relation, and possibly partitions thereof */
+ /*
+ * Process a specific relation, and possibly partitions or child
+ * tables thereof.
+ */
Oid relid;
HeapTuple tuple;
Form_pg_class classForm;
- bool include_parts;
+ bool include_children;
+ bool is_partitioned_table;
int rvr_opts;
/*
@@ -944,20 +948,31 @@ expand_vacuum_rel(VacuumRelation *vrel, MemoryContext vac_context,
MemoryContextSwitchTo(oldcontext);
}
+ /*
+ * Vacuuming a partitioned table with ONLY will not do anything since
+ * the partitioned table itself is empty. Issue a warning if the user
+ * requests this.
+ */
+ include_children = vrel->relation->inh;
+ is_partitioned_table = (classForm->relkind == RELKIND_PARTITIONED_TABLE);
+ if ((options & VACOPT_VACUUM) && is_partitioned_table && !include_children)
+ ereport(WARNING,
+ (errmsg("VACUUM ONLY of partitioned table \"%s\" has no effect",
+ vrel->relation->relname)));
- include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE);
ReleaseSysCache(tuple);
/*
- * If it is, make relation list entries for its partitions. Note that
- * the list returned by find_all_inheritors() includes the passed-in
- * OID, so we have to skip that. There's no point in taking locks on
- * the individual partitions yet, and doing so would just add
- * unnecessary deadlock risk. For this last reason we do not check
- * yet the ownership of the partitions, which get added to the list to
- * process. Ownership will be checked later on anyway.
+ * Unless the user has specified ONLY, make relation list entries for
+ * its partitions or inheritance child tables. Note that the list
+ * returned by find_all_inheritors() includes the passed-in OID, so we
+ * have to skip that. There's no point in taking locks on the
+ * individual partitions or child tables yet, and doing so would just
+ * add unnecessary deadlock risk. For this last reason, we do not yet
+ * check the ownership of the partitions/tables, which get added to
+ * the list to process. Ownership will be checked later on anyway.
*/
- if (include_parts)
+ if (include_children)
{
List *part_oids = find_all_inheritors(relid, NoLock, NULL);
ListCell *part_lc;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ab304ca989d..b1d4642c59b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11921,7 +11921,7 @@ opt_name_list:
;
vacuum_relation:
- qualified_name opt_name_list
+ relation_expr opt_name_list
{
$$ = (Node *) makeVacuumRelation($1, InvalidOid, $2);
}
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index 2eba7128876..1a07dbf67d6 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -291,6 +291,98 @@ ANALYZE vactst, vactst;
BEGIN; -- ANALYZE behaves differently inside a transaction block
ANALYZE vactst, vactst;
COMMIT;
+--
+-- Tests for ANALYZE ONLY / VACUUM ONLY on partitioned tables
+--
+CREATE TABLE only_parted (a int, b text) PARTITION BY LIST (a);
+CREATE TABLE only_parted1 PARTITION OF only_parted FOR VALUES IN (1);
+INSERT INTO only_parted VALUES (1, 'a');
+-- Ensure only the partitioned table is analyzed
+ANALYZE ONLY only_parted;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+--------------+----------+----------
+ only_parted | t | f
+ only_parted1 | f | f
+(2 rows)
+
+-- Ensure partitioned table and the partitions are analyzed
+ANALYZE only_parted;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+--------------+----------+----------
+ only_parted | t | f
+ only_parted1 | t | f
+(2 rows)
+
+DROP TABLE only_parted;
+-- VACUUM ONLY on a partitioned table does nothing, ensure we get a warning.
+VACUUM ONLY vacparted;
+WARNING: VACUUM ONLY of partitioned table "vacparted" has no effect
+-- Try ANALYZE ONLY with a column list
+ANALYZE ONLY vacparted(a,b);
+--
+-- Tests for VACUUM ONLY / ANALYZE ONLY on inheritance tables
+--
+CREATE TABLE only_inh_parent (a int primary key, b TEXT);
+CREATE TABLE only_inh_child () INHERITS (only_inh_parent);
+INSERT INTO only_inh_child(a,b) VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+-- Ensure only parent is analyzed
+ANALYZE ONLY only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+-----------------+----------+----------
+ only_inh_child | f | f
+ only_inh_parent | t | f
+(2 rows)
+
+-- Ensure the parent and child are analyzed
+ANALYZE only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+-----------------+----------+----------
+ only_inh_child | t | f
+ only_inh_parent | t | f
+(2 rows)
+
+-- Ensure only the parent is vacuumed
+VACUUM ONLY only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+-----------------+----------+----------
+ only_inh_child | t | f
+ only_inh_parent | t | t
+(2 rows)
+
+-- Ensure parent and child are vacuumed
+VACUUM only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+ relname | analyzed | vacuumed
+-----------------+----------+----------
+ only_inh_child | t | t
+ only_inh_parent | t | t
+(2 rows)
+
+DROP TABLE only_inh_parent CASCADE;
+NOTICE: drop cascades to table only_inh_child
-- parenthesized syntax for ANALYZE
ANALYZE (VERBOSE) does_not_exist;
ERROR: relation "does_not_exist" does not exist
diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql
index 548cd7accac..5e55079e718 100644
--- a/src/test/regress/sql/vacuum.sql
+++ b/src/test/regress/sql/vacuum.sql
@@ -233,6 +233,72 @@ BEGIN; -- ANALYZE behaves differently inside a transaction block
ANALYZE vactst, vactst;
COMMIT;
+--
+-- Tests for ANALYZE ONLY / VACUUM ONLY on partitioned tables
+--
+CREATE TABLE only_parted (a int, b text) PARTITION BY LIST (a);
+CREATE TABLE only_parted1 PARTITION OF only_parted FOR VALUES IN (1);
+INSERT INTO only_parted VALUES (1, 'a');
+
+-- Ensure only the partitioned table is analyzed
+ANALYZE ONLY only_parted;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass)
+ ORDER BY relname;
+
+-- Ensure partitioned table and the partitions are analyzed
+ANALYZE only_parted;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass)
+ ORDER BY relname;
+
+DROP TABLE only_parted;
+
+-- VACUUM ONLY on a partitioned table does nothing, ensure we get a warning.
+VACUUM ONLY vacparted;
+
+-- Try ANALYZE ONLY with a column list
+ANALYZE ONLY vacparted(a,b);
+
+--
+-- Tests for VACUUM ONLY / ANALYZE ONLY on inheritance tables
+--
+CREATE TABLE only_inh_parent (a int primary key, b TEXT);
+CREATE TABLE only_inh_child () INHERITS (only_inh_parent);
+INSERT INTO only_inh_child(a,b) VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+
+-- Ensure only parent is analyzed
+ANALYZE ONLY only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+
+-- Ensure the parent and child are analyzed
+ANALYZE only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+
+-- Ensure only the parent is vacuumed
+VACUUM ONLY only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+
+-- Ensure parent and child are vacuumed
+VACUUM only_inh_parent;
+SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed
+ FROM pg_stat_user_tables
+ WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass)
+ ORDER BY relname;
+
+DROP TABLE only_inh_parent CASCADE;
+
-- parenthesized syntax for ANALYZE
ANALYZE (VERBOSE) does_not_exist;
ANALYZE (nonexistent-arg) does_not_exist;