diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index 45dee10..9843658 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation -ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ] +ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ] [, ...] @@ -38,10 +38,11 @@ ANALYZE [ VERBOSE ] [ table_name [ - With no parameter, ANALYZE examines every table in the - current database. With a parameter, ANALYZE examines - only that table. It is further possible to give a list of column names, - in which case only the statistics for those columns are collected. + With no parameters, ANALYZE examines every table in the + current database. With parameters, ANALYZE examines + only the tables specified. It is further possible to give a list of + column names for each table, in which case only the statistics for those + columns are collected. diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 421c18d..84bd7eb 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -21,9 +21,9 @@ PostgreSQL documentation -VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE | DISABLE_PAGE_SKIPPING } [, ...] ) ] [ table_name [ (column_name [, ...] ) ] ] -VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table_name ] -VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table_name [ (column_name [, ...] ) ] ] +VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE | DISABLE_PAGE_SKIPPING } [, ...] ) ] [ table_name [ (column_name [, ...] ) ] ] [, ...] +VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table_name ] [, ...] +VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table_name [ (column_name [, ...] ) ] ] [, ...] @@ -40,9 +40,10 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ - With no parameter, VACUUM processes every table in the + With no parameters, VACUUM processes every table in the current database that the current user has permission to vacuum. - With a parameter, VACUUM processes only that table. + With parameters, VACUUM processes only the tables + specified. diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 9fbb0eb..ef3106e 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -67,7 +67,7 @@ static BufferAccessStrategy vac_strategy; /* non-export function prototypes */ -static List *get_rel_oids(Oid relid, const RangeVar *vacrel); +static int get_rel_oids(List **vacrels); static void vac_truncate_clog(TransactionId frozenXID, MultiXactId minMulti, TransactionId lastSaneFrozenXid, @@ -85,13 +85,16 @@ void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) { VacuumParams params; + ListCell *lc; /* sanity checks on options */ Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE)); Assert((vacstmt->options & VACOPT_VACUUM) || !(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE))); - Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL); Assert(!(vacstmt->options & VACOPT_SKIPTOAST)); + foreach(lc, vacstmt->rels) + Assert((((RelationAndColumns *) lfirst(lc))->options & VACOPT_ANALYZE) || + ((RelationAndColumns *) lfirst(lc))->va_cols == NIL); /* * All freeze ages are zero if the FREEZE option is given; otherwise pass @@ -119,8 +122,7 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) params.log_min_duration = -1; /* Now go through the common routine */ - vacuum(vacstmt->options, vacstmt->relation, InvalidOid, ¶ms, - vacstmt->va_cols, NULL, isTopLevel); + vacuum(vacstmt->options, vacstmt->rels, ¶ms, NULL, isTopLevel); } /* @@ -128,15 +130,12 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) * * options is a bitmask of VacuumOption flags, indicating what to do. * - * relid, if not InvalidOid, indicate the relation to process; otherwise, - * the RangeVar is used. (The latter must always be passed, because it's - * used for error messages.) + * If we intend to process all relations, the 'relations' argument may be + * NIL. * * params contains a set of parameters that can be used to customize the * behavior. * - * va_cols is a list of columns to analyze, or NIL to process them all. - * * bstrategy is normally given as NULL, but in autovacuum it can be passed * in to use the same buffer strategy object across multiple vacuum() calls. * @@ -146,14 +145,17 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) * memory context that will not disappear at transaction commit. */ void -vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, - List *va_cols, BufferAccessStrategy bstrategy, bool isTopLevel) +vacuum(int options, List *relations, VacuumParams *params, + BufferAccessStrategy bstrategy, bool isTopLevel) { - const char *stmttype; - volatile bool in_outer_xact, - use_own_xacts; - List *relations; - static bool in_vacuum = false; + const char *stmttype; + volatile bool in_outer_xact, + use_own_xacts; + static bool in_vacuum = false; + MemoryContext oldcontext; + List *temp_relations = NIL; /* for copying the relations list */ + ListCell *relation; + int oid_count; Assert(params != NULL); @@ -226,10 +228,20 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, vac_strategy = bstrategy; /* + * Move our relation list to our special memory context so that we do + * not lose it among our per-relation transactions. + */ + oldcontext = MemoryContextSwitchTo(vac_context); + foreach(relation, relations) + temp_relations = lappend(temp_relations, copyObject(lfirst(relation))); + MemoryContextSwitchTo(oldcontext); + relations = temp_relations; + + /* * Build list of relations to process, unless caller gave us one. (If we * build one, we put it in vac_context for safekeeping.) */ - relations = get_rel_oids(relid, relation); + oid_count = get_rel_oids(&relations); /* * Decide whether we need to start/commit our own transactions. @@ -254,7 +266,7 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, use_own_xacts = true; else if (in_outer_xact) use_own_xacts = false; - else if (list_length(relations) > 1) + else if (oid_count > 1) use_own_xacts = true; else use_own_xacts = false; @@ -283,8 +295,6 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, /* Turn vacuum cost accounting on or off */ PG_TRY(); { - ListCell *cur; - in_vacuum = true; VacuumCostActive = (VacuumCostDelay > 0); VacuumCostBalance = 0; @@ -295,36 +305,41 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, /* * Loop to process each selected relation. */ - foreach(cur, relations) + foreach(relation, relations) { - Oid relid = lfirst_oid(cur); + RelationAndColumns *relinfo = (RelationAndColumns *) lfirst(relation); + int per_table_opts = options | relinfo->options; /* VACOPT_ANALYZE may be set per-table */ + ListCell *oid; - if (options & VACOPT_VACUUM) + foreach(oid, relinfo->oids) { - if (!vacuum_rel(relid, relation, options, params)) - continue; - } - - if (options & VACOPT_ANALYZE) - { - /* - * If using separate xacts, start one for analyze. Otherwise, - * we can use the outer transaction. - */ - if (use_own_xacts) + if (per_table_opts & VACOPT_VACUUM) { - StartTransactionCommand(); - /* functions in indexes may want a snapshot set */ - PushActiveSnapshot(GetTransactionSnapshot()); + if (!vacuum_rel(lfirst_oid(oid), relinfo->relation, per_table_opts, params)) + continue; } - analyze_rel(relid, relation, options, params, - va_cols, in_outer_xact, vac_strategy); - - if (use_own_xacts) + if (per_table_opts & VACOPT_ANALYZE) { - PopActiveSnapshot(); - CommitTransactionCommand(); + /* + * If using separate xacts, start one for analyze. Otherwise, + * we can use the outer transaction. + */ + if (use_own_xacts) + { + StartTransactionCommand(); + /* functions in indexes may want a snapshot set */ + PushActiveSnapshot(GetTransactionSnapshot()); + } + + analyze_rel(lfirst_oid(oid), relinfo->relation, per_table_opts, params, + relinfo->va_cols, in_outer_xact, vac_strategy); + + if (use_own_xacts) + { + PopActiveSnapshot(); + CommitTransactionCommand(); + } } } } @@ -378,62 +393,72 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params, * The list is built in vac_context so that it will survive across our * per-relation transactions. */ -static List * -get_rel_oids(Oid relid, const RangeVar *vacrel) +static int +get_rel_oids(List **vacrels) { - List *oid_list = NIL; + RelationAndColumns *relinfo; MemoryContext oldcontext; + int oid_count = 0; - /* OID supplied by VACUUM's caller? */ - if (OidIsValid(relid)) - { - oldcontext = MemoryContextSwitchTo(vac_context); - oid_list = lappend_oid(oid_list, relid); - MemoryContextSwitchTo(oldcontext); - } - else if (vacrel) + if (*vacrels != NIL) { - /* Process a specific relation */ - Oid relid; - HeapTuple tuple; - Form_pg_class classForm; - bool include_parts; + /* Process specific relation(s) */ + ListCell *lc; - /* - * Since we don't take a lock here, the relation might be gone, or the - * RangeVar might no longer refer to the OID we look up here. In the - * former case, VACUUM will do nothing; in the latter case, it will - * process the OID we looked up here, rather than the new one. Neither - * is ideal, but there's little practical alternative, since we're - * going to commit this transaction and begin a new one between now - * and then. - */ - relid = RangeVarGetRelid(vacrel, NoLock, false); + foreach(lc, *vacrels) + { + Oid relid; + HeapTuple tuple; + Form_pg_class classForm; + bool include_parts; - /* - * To check whether the relation is a partitioned table, fetch its - * syscache entry. - */ - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for relation %u", relid); - classForm = (Form_pg_class) GETSTRUCT(tuple); - include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE); - ReleaseSysCache(tuple); + relinfo = (RelationAndColumns *) lfirst(lc); - /* - * Make relation list entries for this guy and its partitions, if any. - * Note that the list returned by find_all_inheritors() include the - * passed-in OID at its head. Also note that we did not request a - * lock to be taken to match what would be done otherwise. - */ - oldcontext = MemoryContextSwitchTo(vac_context); - if (include_parts) - oid_list = list_concat(oid_list, - find_all_inheritors(relid, NoLock, NULL)); - else - oid_list = lappend_oid(oid_list, relid); - MemoryContextSwitchTo(oldcontext); + /* OIDs supplied by VACUUM's caller? */ + if (relinfo->oids != NIL) + { + oid_count += list_length(relinfo->oids); + continue; + } + + /* + * Since we don't take a lock here, the relation might be gone, or the + * RangeVar might no longer refer to the OID we look up here. In the + * former case, VACUUM will do nothing; in the latter case, it will + * process the OID we looked up here, rather than the new one. Neither + * is ideal, but there's little practical alternative, since we're + * going to commit this transaction and begin a new one between now + * and then. + */ + relid = RangeVarGetRelid(relinfo->relation, NoLock, false); + + /* + * To check whether the relation is a partitioned table, fetch its + * syscache entry. + */ + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation %u", relid); + classForm = (Form_pg_class) GETSTRUCT(tuple); + include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE); + ReleaseSysCache(tuple); + + /* + * Make relation list entries for this guy and its partitions, if any. + * Note that the list returned by find_all_inheritors() include the + * passed-in OID at its head. Also note that we did not request a + * lock to be taken to match what would be done otherwise. + */ + oldcontext = MemoryContextSwitchTo(vac_context); + if (include_parts) + relinfo->oids = find_all_inheritors(relid, NoLock, NULL); + else + relinfo->oids = list_make1_oid(relid); + + oid_count += list_length(relinfo->oids); + + MemoryContextSwitchTo(oldcontext); + } } else { @@ -465,7 +490,20 @@ get_rel_oids(Oid relid, const RangeVar *vacrel) /* Make a relation list entry for this guy */ oldcontext = MemoryContextSwitchTo(vac_context); - oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple)); + + /* + * It is safe to leave everything except the OID empty here. + * Since no tables were specified in the VacuumStmt, we know + * we don't have any columns or extra options to keep track + * of. Also, we do not need the RangeVar, because it is only + * used for error messaging for autovacuum, and autovacuum + * currently always specifies one relation. + */ + relinfo = makeNode(RelationAndColumns); + relinfo->oids = list_make1_oid(HeapTupleGetOid(tuple)); + *vacrels = lappend(*vacrels, relinfo); + ++oid_count; + MemoryContextSwitchTo(oldcontext); } @@ -473,7 +511,7 @@ get_rel_oids(Oid relid, const RangeVar *vacrel) heap_close(pgclass, AccessShareLock); } - return oid_list; + return oid_count; } /* diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 6ad3844..0e9af95 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3761,8 +3761,20 @@ _copyVacuumStmt(const VacuumStmt *from) VacuumStmt *newnode = makeNode(VacuumStmt); COPY_SCALAR_FIELD(options); + COPY_NODE_FIELD(rels); + + return newnode; +} + +static RelationAndColumns * +_copyRelationAndColumns(const RelationAndColumns *from) +{ + RelationAndColumns *newnode = makeNode(RelationAndColumns); + + COPY_SCALAR_FIELD(options); COPY_NODE_FIELD(relation); COPY_NODE_FIELD(va_cols); + COPY_NODE_FIELD(oids); return newnode; } @@ -5209,6 +5221,9 @@ copyObjectImpl(const void *from) case T_VacuumStmt: retval = _copyVacuumStmt(from); break; + case T_RelationAndColumns: + retval = _copyRelationAndColumns(from); + break; case T_ExplainStmt: retval = _copyExplainStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index c9a8c34..755b2b2 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1663,8 +1663,18 @@ static bool _equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b) { COMPARE_SCALAR_FIELD(options); + COMPARE_NODE_FIELD(rels); + + return true; +} + +static bool +_equalRelationAndColumns(const RelationAndColumns *a, const RelationAndColumns *b) +{ + COMPARE_SCALAR_FIELD(options); COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(va_cols); + COMPARE_NODE_FIELD(oids); return true; } @@ -3360,6 +3370,9 @@ equal(const void *a, const void *b) case T_VacuumStmt: retval = _equalVacuumStmt(a, b); break; + case T_RelationAndColumns: + retval = _equalRelationAndColumns(a, b); + break; case T_ExplainStmt: retval = _equalExplainStmt(a, b); break; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 2822331..2a3c5af 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -366,6 +366,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type import_qualification_type %type import_qualification +%type relation_and_columns + %type stmtblock stmtmulti OptTableElementList TableElementList OptInherit definition OptTypedTableElementList TypedTableElementList @@ -395,7 +397,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); relation_expr_list dostmt_opt_list transform_element_list transform_type_list TriggerTransitions TriggerReferencing - publication_name_list + publication_name_list relation_and_columns_list %type group_by_list %type group_by_item empty_grouping_set rollup_clause cube_clause @@ -10148,11 +10150,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose n->options |= VACOPT_FREEZE; if ($4) n->options |= VACOPT_VERBOSE; - n->relation = NULL; - n->va_cols = NIL; - $$ = (Node *)n; + n->rels = NIL; + $$ = (Node *) n; } - | VACUUM opt_full opt_freeze opt_verbose qualified_name + | VACUUM opt_full opt_freeze opt_verbose relation_and_columns_list { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM; @@ -10162,9 +10163,8 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose n->options |= VACOPT_FREEZE; if ($4) n->options |= VACOPT_VERBOSE; - n->relation = $5; - n->va_cols = NIL; - $$ = (Node *)n; + n->rels = $5; + $$ = (Node *) n; } | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt { @@ -10176,24 +10176,20 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose n->options |= VACOPT_FREEZE; if ($4) n->options |= VACOPT_VERBOSE; - $$ = (Node *)n; + $$ = (Node *) n; } | VACUUM '(' vacuum_option_list ')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM | $3; - n->relation = NULL; - n->va_cols = NIL; + n->rels = NIL; $$ = (Node *) n; } - | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list + | VACUUM '(' vacuum_option_list ')' relation_and_columns_list { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM | $3; - n->relation = $5; - n->va_cols = $6; - if (n->va_cols != NIL) /* implies analyze */ - n->options |= VACOPT_ANALYZE; + n->rels = $5; $$ = (Node *) n; } ; @@ -10227,19 +10223,17 @@ AnalyzeStmt: n->options = VACOPT_ANALYZE; if ($2) n->options |= VACOPT_VERBOSE; - n->relation = NULL; - n->va_cols = NIL; - $$ = (Node *)n; + n->rels = NIL; + $$ = (Node *) n; } - | analyze_keyword opt_verbose qualified_name opt_name_list + | analyze_keyword opt_verbose relation_and_columns_list { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; if ($2) n->options |= VACOPT_VERBOSE; - n->relation = $3; - n->va_cols = $4; - $$ = (Node *)n; + n->rels = $3; + $$ = (Node *) n; } ; @@ -10266,6 +10260,24 @@ opt_name_list: | /*EMPTY*/ { $$ = NIL; } ; +relation_and_columns: + qualified_name opt_name_list + { + RelationAndColumns *n = makeNode(RelationAndColumns); + n->options = 0; + n->relation = $1; + n->va_cols = $2; + if (n->va_cols != NIL) /* implies analyze */ + n->options |= VACOPT_ANALYZE; + $$ = (Node *) n; + } + ; + +relation_and_columns_list: + relation_and_columns { $$ = list_make1($1); } + | relation_and_columns_list ',' relation_and_columns { $$ = lappend($1, $3); } + ; + /***************************************************************************** * diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 89dd3b3..13475bb 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3114,6 +3114,7 @@ static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy) { RangeVar rangevar; + RelationAndColumns *rel; /* Set up command parameters --- use local variables instead of palloc */ MemSet(&rangevar, 0, sizeof(rangevar)); @@ -3125,8 +3126,12 @@ autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy) /* Let pgstat know what we're doing */ autovac_report_activity(tab); - vacuum(tab->at_vacoptions, &rangevar, tab->at_relid, &tab->at_params, NIL, - bstrategy, true); + rel = makeNode(RelationAndColumns); + rel->relation = &rangevar; + if (OidIsValid(tab->at_relid)) + rel->oids = list_make1_oid(tab->at_relid); + + vacuum(tab->at_vacoptions, list_make1(rel), &tab->at_params, bstrategy, true); } /* diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 541c2fa..6c77fe9 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -158,8 +158,7 @@ extern int vacuum_multixact_freeze_table_age; /* in commands/vacuum.c */ extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel); -extern void vacuum(int options, RangeVar *relation, Oid relid, - VacuumParams *params, List *va_cols, +extern void vacuum(int options, List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel); extern void vac_open_indexes(Relation relation, LOCKMODE lockmode, int *nindexes, Relation **Irel); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index f59d719..f66f18c 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -468,6 +468,7 @@ typedef enum NodeTag T_PartitionSpec, T_PartitionBoundSpec, T_PartitionRangeDatum, + T_RelationAndColumns, /* * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d396be3..b2de803 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3062,12 +3062,24 @@ typedef enum VacuumOption VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */ } VacuumOption; +/* + * This is used to keep track of a relation and an optional list of + * column names, as may be specified in VACUUM and ANALYZE. + */ +typedef struct RelationAndColumns +{ + NodeTag type; + int options; /* OR of extra VacuumOption flags to apply */ + RangeVar *relation; /* single table to process */ + List *va_cols; /* list of column names, or NIL for all */ + List *oids; /* corresponding OIDs (filled in by vacuum.c) */ +} RelationAndColumns; + typedef struct VacuumStmt { - NodeTag type; - int options; /* OR of VacuumOption flags */ - RangeVar *relation; /* single table to process, or NULL */ - List *va_cols; /* list of column names, or NIL for all */ + NodeTag type; + int options; /* OR of VacuumOption flags */ + List *rels; /* list of tables/columns to process, or NIL for all */ } VacuumStmt; /* ---------------------- diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 6f68663..922a3a4 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -80,8 +80,6 @@ CONTEXT: SQL function "do_analyze" statement 1 SQL function "wrap_do_analyze" statement 1 VACUUM FULL vactst; VACUUM (DISABLE_PAGE_SKIPPING) vaccluster; -DROP TABLE vaccluster; -DROP TABLE vactst; -- partitioned table CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a); CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1); @@ -90,4 +88,20 @@ UPDATE vacparted SET b = 'b'; VACUUM (ANALYZE) vacparted; VACUUM (FULL) vacparted; VACUUM (FREEZE) vacparted; +-- multiple tables specified +VACUUM FREEZE vaccluster, vactst; +VACUUM FREEZE vacparted, does_not_exist; +ERROR: relation "does_not_exist" does not exist +VACUUM (FREEZE) vacparted, vaccluster, vactst; +VACUUM (FREEZE) vaccluster, does_not_exist; +ERROR: relation "does_not_exist" does not exist +VACUUM (FREEZE) vactst (i); +VACUUM (FREEZE) vactst, vacparted (a); +VACUUM (FREEZE) vaccluster, vactst (i), vacparted; +VACUUM (FREEZE) vactst (i), vacparted (a, b), vaccluster (i); +VACUUM; +ANALYZE vactst, vacparted; +ANALYZE vacparted (b), vactst; +DROP TABLE vaccluster; +DROP TABLE vactst; DROP TABLE vacparted; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 7c5fb04..dcd6456 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -62,9 +62,6 @@ VACUUM FULL vactst; VACUUM (DISABLE_PAGE_SKIPPING) vaccluster; -DROP TABLE vaccluster; -DROP TABLE vactst; - -- partitioned table CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a); CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1); @@ -73,4 +70,20 @@ UPDATE vacparted SET b = 'b'; VACUUM (ANALYZE) vacparted; VACUUM (FULL) vacparted; VACUUM (FREEZE) vacparted; + +-- multiple tables specified +VACUUM FREEZE vaccluster, vactst; +VACUUM FREEZE vacparted, does_not_exist; +VACUUM (FREEZE) vacparted, vaccluster, vactst; +VACUUM (FREEZE) vaccluster, does_not_exist; +VACUUM (FREEZE) vactst (i); +VACUUM (FREEZE) vactst, vacparted (a); +VACUUM (FREEZE) vaccluster, vactst (i), vacparted; +VACUUM (FREEZE) vactst (i), vacparted (a, b), vaccluster (i); +VACUUM; +ANALYZE vactst, vacparted; +ANALYZE vacparted (b), vactst; + +DROP TABLE vaccluster; +DROP TABLE vactst; DROP TABLE vacparted;