diff --git a/bin/pg_repack.c b/bin/pg_repack.c index 88cd626a..1702a4fd 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -243,6 +243,8 @@ static bool alldb = false; static bool noorder = false; static SimpleStringList parent_table_list = {NULL, NULL}; static SimpleStringList table_list = {NULL, NULL}; +static SimpleStringList exclude_table_list = {NULL, NULL}; +static SimpleStringList exclude_parent_table_list = {NULL, NULL}; static SimpleStringList schema_list = {NULL, NULL}; static char *orderby = NULL; static char *tablespace = NULL; @@ -287,6 +289,8 @@ static pgut_option options[] = { 'b', 'D', "no-kill-backend", &no_kill_backend }, { 'b', 'k', "no-superuser-check", &no_superuser_check }, { 'l', 'C', "exclude-extension", &exclude_extension_list }, + { 'l', 4, "exclude-table", &exclude_table_list }, + { 'l', 3, "exclude-parent-table", &exclude_parent_table_list }, { 'b', 2, "error-on-invalid-index", &error_on_invalid_index }, { 'i', 1, "switch-threshold", &switch_threshold }, { 0 }, @@ -333,6 +337,9 @@ main(int argc, char *argv[]) else if (only_indexes && exclude_extension_list.head) ereport(ERROR, (errcode(EINVAL), errmsg("cannot specify --only-indexes (-x) and --exclude-extension (-C)"))); + else if ((only_indexes || r_index.head) && exclude_table_list.head) + ereport(ERROR, (errcode(EINVAL), + errmsg("cannot specify --only-indexes (-x) or --index (-i) with --exclude-table"))); else if (alldb) ereport(ERROR, (errcode(EINVAL), errmsg("cannot repack specific index(es) in all databases"))); @@ -362,6 +369,21 @@ main(int argc, char *argv[]) (errcode(EINVAL), errmsg("cannot repack specific table(s) in schema, use schema.table notation instead"))); + if (schema_list.head && ( exclude_table_list.head || exclude_parent_table_list.head )) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot exclude specific table(s) in schema, use schema.table notation instead"))); + + if (exclude_table_list.head && (table_list.head || parent_table_list.head || exclude_extension_list.head)) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot specify --exclude-table along with --table (-t), --parent-table (-I) and --exclude-extension (-C)"))); + + if (exclude_parent_table_list.head && (table_list.head || parent_table_list.head || exclude_extension_list.head)) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot specify --exclude-parent-table along with --table (-t), --parent-table (-I) and --exclude-extension (-C)"))); + if (exclude_extension_list.head && table_list.head) ereport(ERROR, (errcode(EINVAL), @@ -385,6 +407,10 @@ main(int argc, char *argv[]) ereport(ERROR, (errcode(EINVAL), errmsg("cannot repack specific schema(s) in all databases"))); + if (exclude_table_list.head || exclude_parent_table_list.head) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot exclude specific tables(s) in all databases"))); repack_all_databases(orderby); } else @@ -579,7 +605,9 @@ is_requested_relation_exists(char *errbuf, size_t errsize){ SimpleStringListCell *cell; num_relations = simple_string_list_size(parent_table_list) + - simple_string_list_size(table_list); + simple_string_list_size(table_list)+ + simple_string_list_size(exclude_table_list)+ + simple_string_list_size(exclude_parent_table_list); /* nothing was implicitly requested, so nothing to do here */ if (num_relations == 0) @@ -600,6 +628,13 @@ is_requested_relation_exists(char *errbuf, size_t errsize){ if (iparam < num_relations) appendStringInfoChar(&sql, ','); } + for (cell = exclude_table_list.head; cell; cell = cell->next) + { + appendStringInfo(&sql, "($%d, 'r')", iparam + 1); + params[iparam++] = cell->val; + if (iparam < num_relations) + appendStringInfoChar(&sql, ','); + } for (cell = parent_table_list.head; cell; cell = cell->next) { appendStringInfo(&sql, "($%d, 'p')", iparam + 1); @@ -607,6 +642,13 @@ is_requested_relation_exists(char *errbuf, size_t errsize){ if (iparam < num_relations) appendStringInfoChar(&sql, ','); } + for (cell = exclude_parent_table_list.head; cell; cell = cell->next) + { + appendStringInfo(&sql, "($%d, 'p')", iparam + 1); + params[iparam++] = cell->val; + if (iparam < num_relations) + appendStringInfoChar(&sql, ','); + } appendStringInfoString(&sql, ") AS given_t(r,kind) WHERE" /* regular --table relation or inherited --parent-table */ @@ -749,18 +791,26 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) num_tables, num_schemas, num_params, - num_excluded_extensions; + num_excluded_extensions, + num_excluded_tables, + num_excluded__parent_tables; + + num_parent_tables = simple_string_list_size(parent_table_list); num_tables = simple_string_list_size(table_list); num_schemas = simple_string_list_size(schema_list); num_excluded_extensions = simple_string_list_size(exclude_extension_list); + num_excluded_tables = simple_string_list_size(exclude_table_list); + num_excluded__parent_tables = simple_string_list_size(exclude_parent_table_list); /* 1st param is the user-specified tablespace */ num_params = num_excluded_extensions + num_parent_tables + num_tables + - num_schemas + 1; + num_schemas + + num_excluded_tables + + num_excluded__parent_tables + 1; params = pgut_malloc(num_params * sizeof(char *)); initStringInfo(&sql); @@ -835,6 +885,44 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) appendStringInfoString(&sql, ", "); } appendStringInfoString(&sql, ")"); + } + else if (num_excluded_tables || num_excluded__parent_tables) + { + if (exclude_table_list.head) + { + appendStringInfoString(&sql, "("); + for (cell = exclude_table_list.head; cell; cell = cell->next) + { + /* Construct exclude table name placeholders to be used by PQexecParams */ + appendStringInfo(&sql, "relid <> $%d::regclass", iparam + 1); + params[iparam++] = cell->val; + elog(INFO, "skipping table \"%s\"", cell->val); + if (cell->next) + appendStringInfoString(&sql, " AND "); + } + appendStringInfoString(&sql, ")"); + } + if (exclude_parent_table_list.head) + { + if (exclude_table_list.head) + appendStringInfoString(&sql, "AND ("); + else + appendStringInfoString(&sql, " ("); + for (cell = exclude_parent_table_list.head; cell; cell = cell->next) + { + /* Construct table name placeholders to be used by PQexecParams */ + appendStringInfo(&sql, + "relid <> ALL(repack.get_table_and_inheritors($%d::regclass))", + iparam + 1); + params[iparam++] = cell->val; + elog(INFO, "skipping parent table \"%s\" with its inheritors", cell->val); + if (cell->next) + appendStringInfoString(&sql, " AND "); + } + appendStringInfoString(&sql, ")"); + } + + } else { @@ -2392,6 +2480,8 @@ pgut_help(bool details) printf(" -Z, --no-analyze don't analyze at end\n"); printf(" -k, --no-superuser-check skip superuser checks in client\n"); printf(" -C, --exclude-extension don't repack tables which belong to specific extension\n"); + printf(" --exclude-table don't repack specific table\n"); + printf(" --exclude-parent-table don't repack specific parent table and its inheritors\n"); printf(" --error-on-invalid-index don't repack tables which belong to specific extension\n"); - printf(" --switch-threshold switch tables when that many tuples are left to catchup\n"); + printf(" --switch-threshold switch tables when that many tuples are left to catchup\n"); } diff --git a/doc/pg_repack.rst b/doc/pg_repack.rst index 35eddc3e..2fbb4d7b 100644 --- a/doc/pg_repack.rst +++ b/doc/pg_repack.rst @@ -123,6 +123,8 @@ Options: -Z, --no-analyze don't analyze at end -k, --no-superuser-check skip superuser checks in client -C, --exclude-extension don't repack tables which belong to specific extension + --exclude-table don't repack specific table + --exclude-parent-table don't repack specific parent table and its inheritors --error-on-invalid-index don't repack when invalid index is found --switch-threshold switch tables when that many tuples are left to catchup @@ -226,6 +228,14 @@ Reorg Options Skip tables that belong to the specified extension(s). Some extensions may heavily depend on such tables at planning time etc. +``--exclude-table`` + Skip the specified table(s) only to repack. Multiple tables may be skipped by + writing multiple ``--exclude-table`` switches. + +``--exclude-parent-table`` + Skip the specified parent table(s) and its inheritors to repack. Multiple tables + may be skipped by writing multiple ``--exclude-parent-table`` switches. + ``--switch-threshold`` Switch tables when that many tuples are left in log table. This setting can be used to avoid the inability to catchup with write-heavy tables. @@ -326,6 +336,16 @@ Move the specified index to tablespace ``tbs``:: $ pg_repack -d test --index idx --tablespace tbs +Skip the specified table(s) to repack ``foo`` in schema ``schema`` in +the database ``test``:: + + $ pg_repack -d test --exclude-table schema.foo + +Skip the specified parent table(s) and its inheritors to repack ``foo`` in +schema ``schema`` in the database ``test``:: + + $ pg_repack -d test --exclude-parent-table schema.foo + Diagnostics -----------