diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/common/reloptions.c | 14 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 17 | ||||
-rw-r--r-- | src/backend/utils/misc/guc_tables.c | 10 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 4 | ||||
-rw-r--r-- | src/include/access/reloptions.h | 1 | ||||
-rw-r--r-- | src/include/commands/vacuum.h | 1 | ||||
-rw-r--r-- | src/include/utils/guc_tables.h | 1 | ||||
-rw-r--r-- | src/include/utils/rel.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/vacuum.out | 27 | ||||
-rw-r--r-- | src/test/regress/sql/vacuum.sql | 10 |
10 files changed, 81 insertions, 5 deletions
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 59fb53e7707..645b5c00467 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -1779,6 +1779,17 @@ fillRelOptions(void *rdopts, Size basesize, char *itempos = ((char *) rdopts) + elems[j].offset; char *string_val; + /* + * If isset_offset is provided, store whether the reloption is + * set there. + */ + if (elems[j].isset_offset > 0) + { + char *setpos = ((char *) rdopts) + elems[j].isset_offset; + + *(bool *) setpos = options[i].isset; + } + switch (options[i].gen->type) { case RELOPT_TYPE_BOOL: @@ -1901,7 +1912,7 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"vacuum_index_cleanup", RELOPT_TYPE_ENUM, offsetof(StdRdOptions, vacuum_index_cleanup)}, {"vacuum_truncate", RELOPT_TYPE_BOOL, - offsetof(StdRdOptions, vacuum_truncate)}, + offsetof(StdRdOptions, vacuum_truncate), offsetof(StdRdOptions, vacuum_truncate_set)}, {"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL, offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)} }; @@ -1981,6 +1992,7 @@ build_local_reloptions(local_relopts *relopts, Datum options, bool validate) elems[i].optname = opt->option->name; elems[i].opttype = opt->option->type; elems[i].offset = opt->offset; + elems[i].isset_offset = 0; /* not supported for local relopts yet */ i++; } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index e81c9a8aba3..f0a7b87808d 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -78,6 +78,7 @@ int vacuum_failsafe_age; int vacuum_multixact_failsafe_age; double vacuum_max_eager_freeze_failure_rate; bool track_cost_delay_timing; +bool vacuum_truncate; /* * Variables for cost-based vacuum delay. The defaults differ between @@ -2198,13 +2199,21 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, ((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate; /* - * Set truncate option based on truncate reloption if it wasn't specified - * in VACUUM command, or when running in an autovacuum worker + * Set truncate option based on truncate reloption or GUC if it wasn't + * specified in VACUUM command, or when running in an autovacuum worker */ if (params->truncate == VACOPTVALUE_UNSPECIFIED) { - if (rel->rd_options == NULL || - ((StdRdOptions *) rel->rd_options)->vacuum_truncate) + StdRdOptions *opts = (StdRdOptions *) rel->rd_options; + + if (opts && opts->vacuum_truncate_set) + { + if (opts->vacuum_truncate) + params->truncate = VACOPTVALUE_ENABLED; + else + params->truncate = VACOPTVALUE_DISABLED; + } + else if (vacuum_truncate) params->truncate = VACOPTVALUE_ENABLED; else params->truncate = VACOPTVALUE_DISABLED; diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index cc8f2b1230a..97cfd6e5a82 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -712,6 +712,7 @@ const char *const config_group_names[] = [STATS_CUMULATIVE] = gettext_noop("Statistics / Cumulative Query and Index Statistics"), [VACUUM_AUTOVACUUM] = gettext_noop("Vacuuming / Automatic Vacuuming"), [VACUUM_COST_DELAY] = gettext_noop("Vacuuming / Cost-Based Vacuum Delay"), + [VACUUM_DEFAULT] = gettext_noop("Vacuuming / Default Behavior"), [VACUUM_FREEZING] = gettext_noop("Vacuuming / Freezing"), [CLIENT_CONN_STATEMENT] = gettext_noop("Client Connection Defaults / Statement Behavior"), [CLIENT_CONN_LOCALE] = gettext_noop("Client Connection Defaults / Locale and Formatting"), @@ -2131,6 +2132,15 @@ struct config_bool ConfigureNamesBool[] = NULL, NULL, NULL }, + { + {"vacuum_truncate", PGC_USERSET, VACUUM_DEFAULT, + gettext_noop("Enables vacuum to truncate empty pages at the end of the table."), + }, + &vacuum_truncate, + true, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index ad54585cf1d..9f31e4071c7 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -714,6 +714,10 @@ autovacuum_worker_slots = 16 # autovacuum worker slots to allocate #vacuum_cost_page_dirty = 20 # 0-10000 credits #vacuum_cost_limit = 200 # 1-10000 credits +# - Default Behavior - + +#vacuum_truncate = on # enable truncation after vacuum + # - Freezing - #vacuum_freeze_table_age = 150000000 diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index 43445cdcc6c..146aed47c2d 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -152,6 +152,7 @@ typedef struct const char *optname; /* option's name */ relopt_type opttype; /* option's datatype */ int offset; /* offset of field in result struct */ + int isset_offset; /* if > 0, offset of "is set" field */ } relopt_parse_elt; /* Local reloption definition */ diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index baacc63f590..bc37a80dc74 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -304,6 +304,7 @@ extern PGDLLIMPORT int vacuum_multixact_freeze_table_age; extern PGDLLIMPORT int vacuum_failsafe_age; extern PGDLLIMPORT int vacuum_multixact_failsafe_age; extern PGDLLIMPORT bool track_cost_delay_timing; +extern PGDLLIMPORT bool vacuum_truncate; /* * Relevant for vacuums implementing eager scanning. Normal vacuums may diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index ab47145ec36..f72ce944d7f 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -89,6 +89,7 @@ enum config_group STATS_CUMULATIVE, VACUUM_AUTOVACUUM, VACUUM_COST_DELAY, + VACUUM_DEFAULT, VACUUM_FREEZING, CLIENT_CONN_STATEMENT, CLIENT_CONN_LOCALE, diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index db3e504c3d2..d94fddd7cef 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -344,6 +344,7 @@ typedef struct StdRdOptions int parallel_workers; /* max number of parallel workers */ StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */ bool vacuum_truncate; /* enables vacuum to truncate a relation */ + bool vacuum_truncate_set; /* whether vacuum_truncate is set */ /* * Fraction of pages in a relation that vacuum can eagerly scan and fail diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 3f91b69b324..0abcc99989e 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -236,6 +236,7 @@ SELECT pg_relation_size('vac_truncate_test') > 0; t (1 row) +SET vacuum_truncate = false; VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') = 0; ?column? @@ -244,6 +245,32 @@ SELECT pg_relation_size('vac_truncate_test') = 0; (1 row) VACUUM (TRUNCATE FALSE, FULL TRUE) vac_truncate_test; +ALTER TABLE vac_truncate_test RESET (vacuum_truncate); +INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); +ERROR: null value in column "i" of relation "vac_truncate_test" violates not-null constraint +DETAIL: Failing row contains (null, null). +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; + ?column? +---------- + t +(1 row) + +RESET vacuum_truncate; +VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; + ?column? +---------- + t +(1 row) + +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') = 0; + ?column? +---------- + t +(1 row) + DROP TABLE vac_truncate_test; -- partitioned table CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a); diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 058add027f1..a72bdb5b619 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -194,9 +194,19 @@ CREATE TEMP TABLE vac_truncate_test(i INT NOT NULL, j text) INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') > 0; +SET vacuum_truncate = false; VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') = 0; VACUUM (TRUNCATE FALSE, FULL TRUE) vac_truncate_test; +ALTER TABLE vac_truncate_test RESET (vacuum_truncate); +INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; +RESET vacuum_truncate; +VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') = 0; DROP TABLE vac_truncate_test; -- partitioned table |