diff --git a/META.json b/META.json index 8e3b64d..79f3137 100644 --- a/META.json +++ b/META.json @@ -2,18 +2,19 @@ "name": "pg_repack", "abstract": "PostgreSQL module for data reorganization", "description": "Reorganize tables in PostgreSQL databases with minimal locks", - "version": "1.2.1", + "version": "1.3-dev0", "maintainer": [ "Josh Kupershmidt ", - "Daniele Varrazzo " + "Daniele Varrazzo ", + "Beena Emerson " ], "tags": [ "bloat", "maintenance", "vacuum", "cluster" ], - "release_status": "stable", + "release_status": "testing", "license": "bsd", "provides": { "pg_repack": { "file": "lib/pg_repack.sql", - "version": "1.2.1", + "version": "1.3-dev0", "abstract": "Reorganize tables in PostgreSQL databases with minimal locks" } }, diff --git a/bin/pg_repack.c b/bin/pg_repack.c index 2979a00..c33c553 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -219,6 +219,7 @@ static bool analyze = true; static bool alldb = false; static bool noorder = false; static SimpleStringList table_list = {NULL, NULL}; +static SimpleStringList schema_list = {NULL, NULL}; static char *orderby = NULL; static char *tablespace = NULL; static bool moveidx = false; @@ -240,6 +241,7 @@ static pgut_option options[] = { { 'b', 'a', "all", &alldb }, { 'l', 't', "table", &table_list }, + { 'l', 'c', "schema", &schema_list }, { 'b', 'n', "no-order", &noorder }, { 'b', 'N', "dry-run", &dryrun }, { 's', 'o', "order-by", &orderby }, @@ -308,6 +310,11 @@ main(int argc, char *argv[]) } else { + if (schema_list.head && table_list.head) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot repack specific table(s) in schema, use schema.table notation instead"))); + if (noorder) orderby = ""; @@ -317,6 +324,10 @@ main(int argc, char *argv[]) ereport(ERROR, (errcode(EINVAL), errmsg("cannot repack specific table(s) in all databases"))); + if (schema_list.head) + ereport(ERROR, + (errcode(EINVAL), + errmsg("cannot repack specific schema(s) in all databases"))); repack_all_databases(orderby); } else @@ -563,12 +574,14 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) const char **params = NULL; int iparam = 0; size_t num_tables; + size_t num_schemas; size_t num_params; num_tables = simple_string_list_size(table_list); + num_schemas = simple_string_list_size(schema_list); /* 1st param is the user-specified tablespace */ - num_params = num_tables + 1; + num_params = num_tables + num_schemas + 1; params = pgut_malloc(num_params * sizeof(char *)); initStringInfo(&sql); @@ -604,6 +617,19 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) } appendStringInfoString(&sql, ")"); } + else if (num_schemas) + { + appendStringInfoString(&sql, "schemaname IN ("); + for (cell = schema_list.head; cell; cell = cell->next) + { + /* Construct schema name placeholders to be used by PQexecParams */ + appendStringInfo(&sql, "$%d", iparam + 1); + params[iparam++] = cell->val; + if (cell->next) + appendStringInfoString(&sql, ", "); + } + appendStringInfoString(&sql, ")"); + } else { appendStringInfoString(&sql, "pkid IS NOT NULL"); @@ -645,6 +671,7 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) table.target_oid = getoid(res, i, c++); table.target_toast = getoid(res, i, c++); table.target_tidx = getoid(res, i, c++); + c++; // Skip schemaname table.pkid = getoid(res, i, c++); table.ckid = getoid(res, i, c++); @@ -1671,6 +1698,7 @@ repack_table_indexes(PGresult *index_details) for (i = 0; i < num; i++) { char *isvalid = getstr(index_details, i, 2); + char *idx_name = getstr(index_details, i, 0); if (isvalid[0] == 't') { @@ -1683,7 +1711,7 @@ repack_table_indexes(PGresult *index_details) "WHERE pgc.relname = 'index_%u' " "AND nsp.nspname = $1", index); params[0] = schema_name; - elog(INFO, "repacking index \"%s\".\"index_%u\"", schema_name, index); + elog(INFO, "repacking index \"%s\".\"%s\"", schema_name, idx_name); res = execute(sql.data, 1, params); if (PQresultStatus(res) != PGRES_TUPLES_OK) { @@ -1837,6 +1865,10 @@ repack_all_indexes(char *errbuf, size_t errsize) if (!preliminary_checks(errbuf, errsize)) goto cleanup; + /* XXX: tighten these ORDER BYs to avoid intermittent installcheck + * failures due to differently-ordered results for some of the + * --only-indexes tests. + */ if (r_index.head) { appendStringInfoString(&sql, @@ -1883,8 +1915,6 @@ repack_all_indexes(char *errbuf, size_t errsize) if(table_list.head) elog(INFO, "repacking indexes of \"%s\"", cell->val); - else - elog(INFO, "repacking \"%s\"", cell->val); if (!repack_table_indexes(res)) elog(WARNING, "repack failed for \"%s\"", cell->val); @@ -1913,6 +1943,7 @@ pgut_help(bool details) printf("Options:\n"); printf(" -a, --all repack all databases\n"); printf(" -t, --table=TABLE repack specific table only\n"); + printf(" -c, --schema=SCHEMA repack tables in specific schema only\n"); printf(" -s, --tablespace=TBLSPC move repacked tables to a new tablespace\n"); printf(" -S, --moveidx move repacked indexes to TBLSPC too\n"); printf(" -o, --order-by=COLUMNS order by columns instead of cluster keys\n"); diff --git a/doc/pg_repack.rst b/doc/pg_repack.rst index 084ebd4..713ec89 100644 --- a/doc/pg_repack.rst +++ b/doc/pg_repack.rst @@ -117,6 +117,7 @@ The following options can be specified in ``OPTIONS``. Options: -a, --all repack all databases -t, --table=TABLE repack specific table only + -c, --schema=SCHEMA repack tables in specific schema only -s, --tablespace=TBLSPC move repacked tables to a new tablespace -S, --moveidx move repacked indexes to *TBLSPC* too -o, --order-by=COLUMNS order by columns instead of cluster keys @@ -155,6 +156,11 @@ Reorg Options reorganized by writing multiple ``-t`` switches. By default, all eligible tables in the target databases are reorganized. +``-c``, ``--schema`` + Repack the tables in the specified schema(s) only. Multiple schemas may + be repacked by writing multiple ``-c`` switches. May be used in + conjunction with ``--tablespace`` to move tables to a different tablespace. + ``-o COLUMNS [,...]``, ``--order-by=COLUMNS [,...]`` Perform an online CLUSTER ordered by the specified columns. @@ -438,6 +444,7 @@ Releases * pg_repack 1.3 * Added ``--dry-run`` to do a dry run. + * Added ``--schema`` to repack only the specified schema. * pg_repack 1.2 diff --git a/lib/pg_repack.sql.in b/lib/pg_repack.sql.in index 80bc2d4..8f7abea 100644 --- a/lib/pg_repack.sql.in +++ b/lib/pg_repack.sql.in @@ -173,6 +173,7 @@ CREATE VIEW repack.tables AS R.oid AS relid, R.reltoastrelid AS reltoastrelid, CASE WHEN R.reltoastrelid = 0 THEN 0 ELSE (SELECT reltoastidxid FROM pg_class WHERE oid = R.reltoastrelid) END AS reltoastidxid, + N.nspname AS schemaname, PK.indexrelid AS pkid, CK.indexrelid AS ckid, repack.get_create_index_type(PK.indexrelid, 'repack.pk_' || R.oid) AS create_pktype, diff --git a/regress/expected/repack.out b/regress/expected/repack.out index 84b0073..e5ab4e0 100644 --- a/regress/expected/repack.out +++ b/regress/expected/repack.out @@ -325,6 +325,8 @@ INFO: repacking table "tbl_pk_uk" -- => OK \! pg_repack --dbname=contrib_regression --table=tbl_pk_uk --only-indexes INFO: repacking indexes of "tbl_pk_uk" +INFO: repacking index "public"."tbl_pk_uk_pkey" +INFO: repacking index "public"."tbl_pk_uk_col2_col1_key" -- => OK \! pg_repack --dbname=contrib_regression --table=tbl_nn_puk WARNING: relation "tbl_nn_puk" must have a primary key or not-null unique keys @@ -361,3 +363,27 @@ INFO: repacking table "trg4" \! pg_repack --dbname=contrib_regression --table=tbl_cluster --dry-run INFO: Dry run enabled, not executing repack INFO: repacking table "tbl_cluster" +-- Test --schema +-- +CREATE SCHEMA test_schema1; +CREATE TABLE test_schema1.tbl1 (id INTEGER PRIMARY KEY); +CREATE TABLE test_schema1.tbl2 (id INTEGER PRIMARY KEY); +CREATE SCHEMA test_schema2; +CREATE TABLE test_schema2.tbl1 (id INTEGER PRIMARY KEY); +CREATE TABLE test_schema2.tbl2 (id INTEGER PRIMARY KEY); +-- => OK +\! pg_repack --dbname=contrib_regression --schema=test_schema1 +INFO: repacking table "test_schema1.tbl1" +INFO: repacking table "test_schema1.tbl2" +-- => OK +\! pg_repack --dbname=contrib_regression --schema=test_schema1 --schema=test_schema2 +INFO: repacking table "test_schema2.tbl1" +INFO: repacking table "test_schema2.tbl2" +INFO: repacking table "test_schema1.tbl2" +INFO: repacking table "test_schema1.tbl1" +-- => ERROR +\! pg_repack --dbname=contrib_regression --schema=test_schema1 --table=tbl1 +ERROR: cannot repack specific table(s) in schema, use schema.table notation instead +-- => ERROR +\! pg_repack --dbname=contrib_regression --all --schema=test_schema1 +ERROR: cannot repack specific schema(s) in all databases diff --git a/regress/expected/tablespace.out b/regress/expected/tablespace.out index 84945a7..3076a43 100644 --- a/regress/expected/tablespace.out +++ b/regress/expected/tablespace.out @@ -135,6 +135,9 @@ INFO: repacking table "testts1" --move all indexes of the table to a tablespace \! pg_repack --dbname=contrib_regression --table=testts1 --only-indexes --tablespace=testts INFO: repacking indexes of "testts1" +INFO: repacking index "public"."testts1_pkey" +INFO: repacking index "public"."testts1_partial_idx" +INFO: repacking index "public"."testts1_with_idx" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -149,6 +152,9 @@ ORDER BY relname; --all indexes of tablespace remain in same tablespace \! pg_repack --dbname=contrib_regression --table=testts1 --only-indexes INFO: repacking indexes of "testts1" +INFO: repacking index "public"."testts1_pkey" +INFO: repacking index "public"."testts1_partial_idx" +INFO: repacking index "public"."testts1_with_idx" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -163,6 +169,9 @@ ORDER BY relname; --move all indexes of the table to pg_default \! pg_repack --dbname=contrib_regression --table=testts1 --only-indexes --tablespace=pg_default INFO: repacking indexes of "testts1" +INFO: repacking index "public"."testts1_pkey" +INFO: repacking index "public"."testts1_partial_idx" +INFO: repacking index "public"."testts1_with_idx" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -173,7 +182,7 @@ ORDER BY relname; --move one index to a tablespace \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=testts -INFO: repacking "testts1_pkey" +INFO: repacking index "public"."testts1_pkey" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -185,7 +194,7 @@ ORDER BY relname; --index tablespace stays as is \! pg_repack --dbname=contrib_regression --index=testts1_pkey -INFO: repacking "testts1_pkey" +INFO: repacking index "public"."testts1_pkey" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -197,7 +206,7 @@ ORDER BY relname; --move index to pg_default \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=pg_default -INFO: repacking "testts1_pkey" +INFO: repacking index "public"."testts1_pkey" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -208,8 +217,8 @@ ORDER BY relname; --using multiple --index option \! pg_repack --dbname=contrib_regression --index=testts1_pkey --index=testts1_with_idx --tablespace=testts -INFO: repacking "testts1_pkey" -INFO: repacking "testts1_with_idx" +INFO: repacking index "public"."testts1_pkey" +INFO: repacking index "public"."testts1_with_idx" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' diff --git a/regress/sql/repack.sql b/regress/sql/repack.sql index 4bc5f9c..03e72cd 100644 --- a/regress/sql/repack.sql +++ b/regress/sql/repack.sql @@ -213,3 +213,20 @@ CREATE TRIGGER zzzzzz AFTER UPDATE ON trg4 FOR EACH ROW EXECUTE PROCEDURE trgtes -- Dry run -- \! pg_repack --dbname=contrib_regression --table=tbl_cluster --dry-run + +-- Test --schema +-- +CREATE SCHEMA test_schema1; +CREATE TABLE test_schema1.tbl1 (id INTEGER PRIMARY KEY); +CREATE TABLE test_schema1.tbl2 (id INTEGER PRIMARY KEY); +CREATE SCHEMA test_schema2; +CREATE TABLE test_schema2.tbl1 (id INTEGER PRIMARY KEY); +CREATE TABLE test_schema2.tbl2 (id INTEGER PRIMARY KEY); +-- => OK +\! pg_repack --dbname=contrib_regression --schema=test_schema1 +-- => OK +\! pg_repack --dbname=contrib_regression --schema=test_schema1 --schema=test_schema2 +-- => ERROR +\! pg_repack --dbname=contrib_regression --schema=test_schema1 --table=tbl1 +-- => ERROR +\! pg_repack --dbname=contrib_regression --all --schema=test_schema1