diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/vacuum.c | 39 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 2 | ||||
-rw-r--r-- | src/test/regress/expected/vacuum.out | 92 | ||||
-rw-r--r-- | src/test/regress/sql/vacuum.sql | 66 |
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; |