diff --git a/bin/pg_repack.c b/bin/pg_repack.c index 36ceed8..fc7b039 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -109,7 +109,7 @@ const char *PROGRAM_VERSION = "unknown"; */ #define SQL_XID_SNAPSHOT_80300 \ "SELECT repack.array_accum(l.virtualtransaction) " \ - " FROM pg_locks AS l" \ + " FROM pg_locks AS l" \ " LEFT JOIN pg_stat_activity AS a " \ " ON l.pid = a.procpid " \ " LEFT JOIN pg_database AS d " \ @@ -174,7 +174,7 @@ typedef struct repack_index { Oid target_oid; /* target: OID */ const char *create_index; /* CREATE INDEX */ - index_status_t status; /* Track parallel build statuses. */ + index_status_t status; /* Track parallel build statuses. */ int worker_idx; /* which worker conn is handling */ } repack_index; @@ -251,6 +251,7 @@ static bool dryrun = false; static unsigned int temp_obj_num = 0; /* temporary objects counter */ static bool no_kill_backend = false; /* abandon when timed-out */ static bool no_superuser_check = false; +static SimpleStringList exclude_extension_list = {NULL, NULL}; /* don't repack tables of these extensions */ /* buffer should have at least 11 bytes */ static char * @@ -278,6 +279,7 @@ static pgut_option options[] = { 'i', 'j', "jobs", &jobs }, { 'b', 'D', "no-kill-backend", &no_kill_backend }, { 'b', 'k', "no-superuser-check", &no_superuser_check }, + { 'l', 'C', "exclude-extension", &exclude_extension_list }, { 0 }, }; @@ -309,9 +311,15 @@ main(int argc, char *argv[]) else if (r_index.head && only_indexes) ereport(ERROR, (errcode(EINVAL), errmsg("cannot specify --index (-i) and --only-indexes (-x)"))); + else if (r_index.head && exclude_extension_list.head) + ereport(ERROR, (errcode(EINVAL), + errmsg("cannot specify --index (-i) and --exclude-extension (-C)"))); else if (only_indexes && !table_list.head) ereport(ERROR, (errcode(EINVAL), errmsg("cannot repack all indexes of database, specify the table(s) via --table (-t)"))); + else if (only_indexes && exclude_extension_list.head) + ereport(ERROR, (errcode(EINVAL), + errmsg("cannot specify --only-indexes (-x) and --exclude-extension (-C)"))); else if (alldb) ereport(ERROR, (errcode(EINVAL), errmsg("cannot repack specific index(es) in all databases"))); @@ -341,6 +349,11 @@ main(int argc, char *argv[]) (errcode(EINVAL), errmsg("cannot repack specific table(s) in schema, use schema.table notation instead"))); + if (exclude_extension_list.head && table_list.head) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot specify --table (-t) and --exclude-extension (-C)"))); + if (noorder) orderby = ""; @@ -605,12 +618,14 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) size_t num_tables; size_t num_schemas; size_t num_params; + size_t num_excluded_extensions; 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); /* 1st param is the user-specified tablespace */ - num_params = num_tables + num_schemas + 1; + num_params = num_excluded_extensions + num_tables + num_schemas + 1; params = pgut_malloc(num_params * sizeof(char *)); initStringInfo(&sql); @@ -663,6 +678,29 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) { appendStringInfoString(&sql, "pkid IS NOT NULL"); } + + /* Exclude tables which belong to extensions */ + if (exclude_extension_list.head) + { + appendStringInfoString(&sql, " AND t.relid NOT IN" + " (SELECT d.objid::regclass" + " FROM pg_depend d JOIN pg_extension e" + " ON d.refobjid = e.oid" + " WHERE d.classid = 'pg_class'::regclass AND ("); + + /* List all excluded extensions */ + for (cell = exclude_extension_list.head; cell; cell = cell->next) + { + appendStringInfo(&sql, "e.extname = $%d", iparam + 1); + params[iparam++] = cell->val; + + appendStringInfoString(&sql, cell->next ? " OR " : ")"); + } + + /* Close subquery */ + appendStringInfoString(&sql, ")"); + } + /* Ensure the regression tests get a consistent ordering of tables */ appendStringInfoString(&sql, " ORDER BY t.relname, t.schemaname"); @@ -2100,4 +2138,5 @@ pgut_help(bool details) printf(" -D, --no-kill-backend don't kill other backends when timed out\n"); 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"); } diff --git a/doc/pg_repack.rst b/doc/pg_repack.rst index 4adafe9..388a261 100644 --- a/doc/pg_repack.rst +++ b/doc/pg_repack.rst @@ -130,6 +130,7 @@ Options: -D, --no-kill-backend don't kill other backends when timed out -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 Connection options: -d, --dbname=DBNAME database to connect @@ -222,6 +223,9 @@ Reorg Options Skip the superuser checks in the client. This setting is useful for using pg_repack on platforms that support running it as non-superusers. +``-C``, ``--exclude-extension`` + Skip tables that belong to the specified extension(s). Some extensions + may heavily depend on such tables at planning time etc. Connection Options ^^^^^^^^^^^^^^^^^^ @@ -473,6 +477,7 @@ Releases CONFLICT`` (issue #106) * added ``--no-kill-backend`` option (issue #108) * added ``--no-superuser-check`` option (issue #114) + * added ``--exclude-extension`` option (#97) * pg_repack 1.3.4 diff --git a/regress/expected/repack.out b/regress/expected/repack.out index 17e3666..4539043 100644 --- a/regress/expected/repack.out +++ b/regress/expected/repack.out @@ -403,3 +403,23 @@ ERROR: pg_repack failed with error: ERROR: permission denied for schema repack LINE 1: select repack.version(), repack.version_sql() ^ DROP ROLE IF EXISTS nosuper; +-- +-- exclude extension check +-- +CREATE SCHEMA exclude_extension_schema; +CREATE TABLE exclude_extension_schema.tbl(val integer primary key); +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=dummy_table --exclude-extension=dummy_extension +ERROR: cannot specify --table (-t) and --exclude-extension (-C) +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=dummy_table --exclude-extension=dummy_extension -x +ERROR: cannot specify --only-indexes (-x) and --exclude-extension (-C) +-- => ERROR +\! pg_repack --dbname=contrib_regression --index=dummy_index --exclude-extension=dummy_extension +ERROR: cannot specify --index (-i) and --exclude-extension (-C) +-- => OK +\! pg_repack --dbname=contrib_regression --schema=exclude_extension_schema --exclude-extension=dummy_extension +INFO: repacking table "exclude_extension_schema.tbl" +-- => OK +\! pg_repack --dbname=contrib_regression --schema=exclude_extension_schema --exclude-extension=dummy_extension --exclude-extension=dummy_extension +INFO: repacking table "exclude_extension_schema.tbl" diff --git a/regress/sql/repack.sql b/regress/sql/repack.sql index e613d63..d7baa7d 100644 --- a/regress/sql/repack.sql +++ b/regress/sql/repack.sql @@ -245,3 +245,19 @@ CREATE ROLE nosuper WITH LOGIN; -- => ERROR \! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check DROP ROLE IF EXISTS nosuper; + +-- +-- exclude extension check +-- +CREATE SCHEMA exclude_extension_schema; +CREATE TABLE exclude_extension_schema.tbl(val integer primary key); +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=dummy_table --exclude-extension=dummy_extension +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=dummy_table --exclude-extension=dummy_extension -x +-- => ERROR +\! pg_repack --dbname=contrib_regression --index=dummy_index --exclude-extension=dummy_extension +-- => OK +\! pg_repack --dbname=contrib_regression --schema=exclude_extension_schema --exclude-extension=dummy_extension +-- => OK +\! pg_repack --dbname=contrib_regression --schema=exclude_extension_schema --exclude-extension=dummy_extension --exclude-extension=dummy_extension