diff --git a/.travis.yml b/.travis.yml index cb55e29..2ffb09c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ dist: trusty sudo: required env: + - PGVER=10 + PGTESTING=1 - PGVER=9.6 - PGVER=9.5 - PGVER=9.4 diff --git a/META.json b/META.json index afb0a4b..1e109dd 100644 --- a/META.json +++ b/META.json @@ -2,7 +2,7 @@ "name": "pg_repack", "abstract": "PostgreSQL module for data reorganization", "description": "Reorganize tables in PostgreSQL databases with minimal locks", - "version": "1.4.0", + "version": "1.4.3", "maintainer": [ "Beena Emerson ", "Josh Kupershmidt ", @@ -15,7 +15,7 @@ "provides": { "pg_repack": { "file": "lib/pg_repack.sql", - "version": "1.4.0", + "version": "1.4.3", "abstract": "Reorganize tables in PostgreSQL databases with minimal locks" } }, diff --git a/Makefile b/Makefile index e132d9f..0abb250 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,13 @@ EXTENSION = pg_repack .PHONY: dist/$(EXTENSION)-$(EXTVERSION).zip # Pull out PostgreSQL version number from pg_config -VERSION := $(shell $(PG_CONFIG) --version | awk '{print $$2}') +VERSION := $(shell $(PG_CONFIG) --version | sed 's/.* \([[:digit:].]\{1,\}\).*/\1/') ifeq ("$(VERSION)","") $(error pg_config not found) endif # PostgreSQL version as a number, e.g. 9.1.4 -> 901 -INTVERSION := $(shell echo $$(($$(echo $(VERSION) | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/')))) +INTVERSION := $(shell echo $$(($$(echo $(VERSION).0 | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/')))) # The version number of the library EXTVERSION = $(shell grep '"version":' META.json | head -1 \ diff --git a/bin/Makefile b/bin/Makefile index bc2f52b..2c63702 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -25,6 +25,10 @@ endif PG_LIBS = $(libpq) +# libs pgport, pgcommon moved somewhere else in some ubuntu version +# see ticket #179 +PG_LIBS += -L$(shell $(PG_CONFIG) --pkglibdir) + USE_PGXS = 1 # use pgxs if not in contrib directory PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) diff --git a/bin/pg_repack.c b/bin/pg_repack.c index c367257..45afdc1 100644 --- a/bin/pg_repack.c +++ b/bin/pg_repack.c @@ -774,6 +774,7 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) for (i = 0; i < num; i++) { repack_table table; + StringInfoData copy_sql; const char *create_table_1; const char *create_table_2; const char *tablespace; @@ -816,17 +817,27 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) table.sql_pop = getstr(res, i, c++); tablespace = getstr(res, i, c++); + /* Craft CREATE TABLE SQL */ resetStringInfo(&sql); appendStringInfoString(&sql, create_table_1); appendStringInfoString(&sql, tablespace); appendStringInfoString(&sql, create_table_2); + + /* Always append WITH NO DATA to CREATE TABLE SQL*/ + appendStringInfoString(&sql, " WITH NO DATA"); + table.create_table = sql.data; + + /* Craft Copy SQL */ + initStringInfo(©_sql); + appendStringInfoString(©_sql, table.copy_data); if (!orderby) + { if (ckey != NULL) { /* CLUSTER mode */ - appendStringInfoString(&sql, " ORDER BY "); - appendStringInfoString(&sql, ckey); + appendStringInfoString(©_sql, " ORDER BY "); + appendStringInfoString(©_sql, ckey); } /* else, VACUUM FULL mode (non-clustered tables) */ @@ -838,13 +849,10 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize) else { /* User specified ORDER BY */ - appendStringInfoString(&sql, " ORDER BY "); - appendStringInfoString(&sql, orderby); + appendStringInfoString(©_sql, " ORDER BY "); + appendStringInfoString(©_sql, orderby); } - - /* Always append WITH NOT DATA */ - appendStringInfoString(&sql, " WITH NO DATA"); - table.create_table = sql.data; + table.copy_data = copy_sql.data; repack_one_table(&table, orderby); } @@ -854,6 +862,7 @@ cleanup: CLEARPGRES(res); disconnect(); termStringInfo(&sql); + free(params); return ret; } @@ -1782,6 +1791,12 @@ lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool sta { elog(WARNING, "timed out, do not cancel conflicting backends"); ret = false; + + /* Before exit the loop reset the transaction */ + if (start_xact) + pgut_rollback(conn); + else + pgut_command(conn, "ROLLBACK TO SAVEPOINT repack_sp1", 0, NULL); break; } else @@ -1922,6 +1937,7 @@ repack_table_indexes(PGresult *index_details) params[1] = utoa(table, buffer[1]); params[2] = tablespace; schema_name = getstr(index_details, 0, 5); + /* table_name is schema-qualified */ table_name = getstr(index_details, 0, 4); /* Keep track of which of the table's indexes we have successfully @@ -1954,7 +1970,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\".\"%s\"", schema_name, idx_name); + elog(INFO, "repacking index \"%s\"", idx_name); res = execute(sql.data, 1, params); if (PQresultStatus(res) != PGRES_TUPLES_OK) { @@ -1986,8 +2002,8 @@ repack_table_indexes(PGresult *index_details) if (PQntuples(res) < 1) { elog(WARNING, - "unable to generate SQL to CREATE work index for %s.%s", - schema_name, getstr(index_details, i, 0)); + "unable to generate SQL to CREATE work index for %s", + getstr(index_details, i, 0)); continue; } @@ -2117,7 +2133,7 @@ repack_all_indexes(char *errbuf, size_t errsize) if (r_index.head) { appendStringInfoString(&sql, - "SELECT i.relname, idx.indexrelid, idx.indisvalid, idx.indrelid, idx.indrelid::regclass, n.nspname" + "SELECT repack.oid2text(i.oid), idx.indexrelid, idx.indisvalid, idx.indrelid, repack.oid2text(idx.indrelid), n.nspname" " FROM pg_index idx JOIN pg_class i ON i.oid = idx.indexrelid" " JOIN pg_namespace n ON n.oid = i.relnamespace" " WHERE idx.indexrelid = $1::regclass ORDER BY indisvalid DESC, i.relname, n.nspname"); @@ -2127,7 +2143,7 @@ repack_all_indexes(char *errbuf, size_t errsize) else if (table_list.head || parent_table_list.head) { appendStringInfoString(&sql, - "SELECT i.relname, idx.indexrelid, idx.indisvalid, idx.indrelid, $1::text, n.nspname" + "SELECT repack.oid2text(i.oid), idx.indexrelid, idx.indisvalid, idx.indrelid, $1::text, n.nspname" " FROM pg_index idx JOIN pg_class i ON i.oid = idx.indexrelid" " JOIN pg_namespace n ON n.oid = i.relnamespace" " WHERE idx.indrelid = $1::regclass ORDER BY indisvalid DESC, i.relname, n.nspname"); diff --git a/bin/pgut/pgut-fe.c b/bin/pgut/pgut-fe.c index 5ed4fed..2f3cba6 100644 --- a/bin/pgut/pgut-fe.c +++ b/bin/pgut/pgut-fe.c @@ -99,6 +99,9 @@ setup_workers(int num_workers) break; } + /* Hardcode a search path to avoid injections into public or pg_temp */ + pgut_command(conn, "SET search_path TO pg_catalog, pg_temp", 0, NULL); + /* Make sure each worker connection can work in non-blocking * mode. */ diff --git a/bin/pgut/pgut.c b/bin/pgut/pgut.c index 66db463..40de8d1 100644 --- a/bin/pgut/pgut.c +++ b/bin/pgut/pgut.c @@ -434,7 +434,26 @@ simple_string_list_size(SimpleStringList list) static char * prompt_for_password(void) { - return simple_prompt("Password: ", 100, false); + char *buf; +#define BUFSIZE 100 + +#if PG_VERSION_NUM < 100000 + buf = simple_prompt("Password: ", BUFSIZE, false); +#else + buf = (char *)malloc(BUFSIZE); + if (buf != NULL) + simple_prompt("Password: ", buf, BUFSIZE, false); +#endif + + if (buf == NULL) + ereport(FATAL, + (errcode_errno(), + errmsg("could not allocate memory (" UINT64_FORMAT " bytes): ", + (uint64) BUFSIZE))); + + return buf; + +#undef BUFSIZE } @@ -485,6 +504,9 @@ pgut_connect(const char *info, YesNo prompt, int elevel) termStringInfo(&add_pass); free(passwd); + /* Hardcode a search path to avoid injections into public or pg_temp */ + pgut_command(conn, "SET search_path TO pg_catalog, pg_temp", 0, NULL); + return conn; } @@ -1306,7 +1328,7 @@ pgut_malloc(size_t size) ereport(FATAL, (errcode_errno(), errmsg("could not allocate memory (" UINT64_FORMAT " bytes): ", - (unsigned long) size))); + (uint64) size))); return ret; } @@ -1319,7 +1341,7 @@ pgut_realloc(void *p, size_t size) ereport(FATAL, (errcode_errno(), errmsg("could not re-allocate memory (" UINT64_FORMAT " bytes): ", - (unsigned long) size))); + (uint64) size))); return ret; } diff --git a/doc/Makefile b/doc/Makefile index 5746f34..5a179ad 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,6 +1,5 @@ RST2HTML = $(shell which rst2html || which rst2html.py) -RSTCSS = $(shell python -c 'import docutils.writers.html4css1 as m; print m.Writer.default_stylesheet_path') -RSTOPTS = --stylesheet-path=style.css,$(RSTCSS) --initial-header-level=2 +RSTOPTS = --stylesheet-path=style.css,html4css1.css --initial-header-level=2 HTML = $(patsubst %.rst,%.html,$(wildcard *.rst)) diff --git a/doc/pg_repack.rst b/doc/pg_repack.rst index 0969676..9e26b24 100644 --- a/doc/pg_repack.rst +++ b/doc/pg_repack.rst @@ -40,7 +40,7 @@ Requirements ------------ PostgreSQL versions - PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6 + PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10 Disks Performing a full-table repack requires free disk space about twice as @@ -410,7 +410,7 @@ pg_repack cannot reorganize temp tables. GiST indexes ^^^^^^^^^^^^ -pg_repack cannot reorganize tables using GiST indexes. +pg_repack cannot cluster tables by GiST indexes. DDL commands ^^^^^^^^^^^^ @@ -466,6 +466,23 @@ Creating indexes concurrently comes with a few caveats, please see `the document Releases -------- +* pg_repack 1.4.3 + + * Fixed possible CVE-2018-1058 attack paths (issue #168) + * Fixed "unexpected index definition" after CVE-2018-1058 changes in + PostgreSQL (issue #169) + * Fixed build with recent Ubuntu packages (issue #179) + +* pg_repack 1.4.2 + + * added PostgreSQL 10 support (issue #120) + * fixed error DROP INDEX CONCURRENTLY cannot run inside a transaction block + (issue #129) + +* pg_repack 1.4.1 + + * fixed broken ``--order-by`` option (issue #138) + * pg_repack 1.4 * added support for PostgreSQL 9.6, dropped support for versions before 9.1 diff --git a/doc/pg_repack_jp.rst b/doc/pg_repack_jp.rst index b958400..4f5fac6 100644 --- a/doc/pg_repack_jp.rst +++ b/doc/pg_repack_jp.rst @@ -62,7 +62,7 @@ pg_repackでは再編成する方法として次のものが選択できます ------------ PostgreSQL versions - PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6 + PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10 Disks Performing a full-table repack requires free disk space about twice as @@ -864,6 +864,35 @@ ACCESS EXCLUSIVEロックを取得します。その他のステップでは、A リリースノート --------------- + +.. * pg_repack 1.4.3 +.. * Fixed possible CVE-2018-1058 attack paths (issue #168) +.. * Fixed "unexpected index definition" after CVE-2018-1058 changes in +.. PostgreSQL (issue #169) +.. * Fixed build with recent Ubuntu packages (issue #179) + +* pg_repack 1.4.3 + + * CVE-2018-1058を利用した攻撃の可能性を修正しました (issue #168) + * PostgreSQLでのCVE-2018-1058の修正により"unexpected index definition"エラーが発生する事象を修正しました (issue #169) + * 最近のUbuntuパッケージでビルドが失敗する事象を修正しました (issue #179) + +.. * pg_repack 1.4.2 +.. * added PostgreSQL 10 support (issue #120) +.. * fixed error DROP INDEX CONCURRENTLY cannot run inside a transaction block (issue #129) + +* pg_repack 1.4.2 + + * PostgreSQL 10をサポートしました (issue #120) + * エラー「DROP INDEX CONCURRENTLY cannot run inside a transaction block」が発生する事象を修正しました (issue #129) + +.. * pg_repack 1.4.1 +.. * fixed broken ``--order-by`` option (issue #138) + +* pg_repack 1.4.1 + + * 壊れていた ``--order-by`` オプションを修正しました (issue #138) + .. * pg_repack 1.4 .. * added support for PostgreSQL 9.6 .. * use ``AFTER`` trigger to solve concurrency problems with ``INSERT diff --git a/doc/release.rst b/doc/release.rst index 8e9719c..299a9cf 100644 --- a/doc/release.rst +++ b/doc/release.rst @@ -24,8 +24,8 @@ with the right privileges: contact Daniele Varrazzo to obtain them. pgxn check dist/pg_repack-$VER.zip (note that ``check`` may require the Postgres bin directory to be added to - the path; check the ``install`` log to see where ``pg_repack`` executable - was installed). + the path, e.g. ``PATH=$(pg_config --bindir):$PATH``; check the ``install`` + log to see where ``pg_repack`` executable was installed). .. __: http://pgxnclient.projects.pgfoundry.org/ diff --git a/lib/Makefile b/lib/Makefile index db2aeda..5730765 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,8 +9,8 @@ PG_CONFIG ?= pg_config # version as a number, e.g. 9.1.4 -> 901 -VERSION := $(shell $(PG_CONFIG) --version | awk '{print $$2}') -INTVERSION := $(shell echo $$(($$(echo $(VERSION) | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/')))) +VERSION := $(shell $(PG_CONFIG) --version | sed 's/.* \([[:digit:].]\{1,\}\).*/\1/') +INTVERSION := $(shell echo $$(($$(echo $(VERSION).0 | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/')))) EXTENSION = pg_repack MODULE_big = $(EXTENSION) @@ -34,9 +34,7 @@ include $(PGXS) # remove dependency on libxml2, libxslt, and libpam. # XXX: find a better way to make sure we are linking with libraries # from pg_config which we actually need. -LIBS := $(filter-out -lxml2, $(LIBS)) -LIBS := $(filter-out -lxslt, $(LIBS)) -LIBS := $(filter-out -lpam, $(LIBS)) +LIBS := $(filter-out -lpam -lxml2 -lxslt, $(LIBS)) pg_repack.sql: pg_repack.sql.in echo "BEGIN;" > $@; \ diff --git a/lib/pg_repack.sql.in b/lib/pg_repack.sql.in index 249547c..99003b6 100644 --- a/lib/pg_repack.sql.in +++ b/lib/pg_repack.sql.in @@ -23,11 +23,13 @@ CREATE AGGREGATE repack.array_accum ( initcond = '{}' ); +-- Always specify search_path to 'pg_catalog' so that we +-- always can get schema-qualified relation name CREATE FUNCTION repack.oid2text(oid) RETURNS text AS $$ SELECT textin(regclassout($1)); $$ -LANGUAGE sql STABLE STRICT; +LANGUAGE sql STABLE STRICT SET search_path to 'pg_catalog'; CREATE FUNCTION repack.get_index_columns(oid, text) RETURNS text AS $$ @@ -235,7 +237,7 @@ CREATE VIEW repack.primary_keys AS GROUP BY indrelid; CREATE VIEW repack.tables AS - SELECT R.oid::regclass AS relname, + SELECT repack.oid2text(R.oid) AS relname, R.oid AS relid, R.reltoastrelid AS reltoastrelid, CASE WHEN R.reltoastrelid = 0 THEN 0 ELSE ( diff --git a/lib/repack.c b/lib/repack.c index 6ba7535..34972ee 100644 --- a/lib/repack.c +++ b/lib/repack.c @@ -35,6 +35,7 @@ #include "storage/lmgr.h" #include "utils/array.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/relcache.h" @@ -353,12 +354,47 @@ get_relation_name(Oid relid) { Oid nsp = get_rel_namespace(relid); char *nspname; + char *strver; + int ver; - /* Qualify the name if not visible in search path */ - if (RelationIsVisible(relid)) - nspname = NULL; + /* Get the version of the running server (PG_VERSION_NUM would return + * the version we compiled the extension with) */ + strver = GetConfigOptionByName("server_version_num", NULL +#if PG_VERSION_NUM >= 90600 + , false /* missing_ok */ +#endif + ); + + ver = atoi(strver); + pfree(strver); + + /* + * Relation names given by PostgreSQL core are always + * qualified since some minor releases. Note that this change + * wasn't introduced in PostgreSQL 9.2 and 9.1 releases. + */ + if ((ver >= 100000 && ver < 100003) || + (ver >= 90600 && ver < 90608) || + (ver >= 90500 && ver < 90512) || + (ver >= 90400 && ver < 90417) || + (ver >= 90300 && ver < 90322) || + (ver >= 90200 && ver < 90300) || + (ver >= 90100 && ver < 90200)) + { + /* Qualify the name if not visible in search path */ + if (RelationIsVisible(relid)) + nspname = NULL; + else + nspname = get_namespace_name(nsp); + } else - nspname = get_namespace_name(nsp); + { + /* Always qualify the name */ + if (OidIsValid(nsp)) + nspname = get_namespace_name(nsp); + else + nspname = NULL; + } return quote_qualified_identifier(nspname, get_rel_name(relid)); } @@ -971,11 +1007,21 @@ repack_drop(PG_FUNCTION_ARGS) * which in turn, is waiting for lock on log_%u table. * * Fixes deadlock mentioned in the Github issue #55. + * + * Skip the lock if we are not going to do anything. + * Otherwise, if repack gets accidentally run twice for the same table + * at the same time, the second repack, in order to perform + * a pointless cleanup, has to wait until the first one completes. + * This adds an ACCESS EXCLUSIVE lock request into the queue + * making the table effectively inaccessible for any other backend. */ - execute_with_format( - SPI_OK_UTILITY, - "LOCK TABLE %s.%s IN ACCESS EXCLUSIVE MODE", - nspname, relname); + if (numobj > 0) + { + execute_with_format( + SPI_OK_UTILITY, + "LOCK TABLE %s.%s IN ACCESS EXCLUSIVE MODE", + nspname, relname); + } /* drop log table: must be done before dropping the pk type, * since the log table is dependent on the pk type. (That's @@ -1156,14 +1202,25 @@ swap_heap_or_index_files(Oid r1, Oid r2) relform2->reltuples = swap_tuples; } + indstate = CatalogOpenIndexes(relRelation); + +#if PG_VERSION_NUM < 100000 + /* Update the tuples in pg_class */ simple_heap_update(relRelation, &reltup1->t_self, reltup1); simple_heap_update(relRelation, &reltup2->t_self, reltup2); /* Keep system catalogs current */ - indstate = CatalogOpenIndexes(relRelation); CatalogIndexInsert(indstate, reltup1); CatalogIndexInsert(indstate, reltup2); + +#else + + CatalogTupleUpdateWithInfo(relRelation, &reltup1->t_self, reltup1, indstate); + CatalogTupleUpdateWithInfo(relRelation, &reltup2->t_self, reltup2, indstate); + +#endif + CatalogCloseIndexes(indstate); /* diff --git a/regress/Makefile b/regress/Makefile index 943f440..0365c9a 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -9,15 +9,15 @@ PG_CONFIG ?= pg_config # version as a number, e.g. 9.1.4 -> 901 -VERSION := $(shell $(PG_CONFIG) --version | awk '{print $$2}') -INTVERSION := $(shell echo $$(($$(echo $(VERSION) | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/' )))) +VERSION := $(shell $(PG_CONFIG) --version | sed 's/.* \([[:digit:].]\{1,\}\).*/\1/') +INTVERSION := $(shell echo $$(($$(echo $(VERSION).0 | sed 's/\([[:digit:]]\{1,\}\)\.\([[:digit:]]\{1,\}\).*/\1*100+\2/')))) # # Test suite # -REGRESS := init-extension repack tablespace issue3 +REGRESS := init-extension repack-setup repack-run after-schema repack-check nosuper tablespace issue3 USE_PGXS = 1 # use pgxs if not in contrib directory PGXS := $(shell $(PG_CONFIG) --pgxs) diff --git a/regress/expected/after-schema.out b/regress/expected/after-schema.out new file mode 100644 index 0000000..571f014 --- /dev/null +++ b/regress/expected/after-schema.out @@ -0,0 +1,75 @@ +-- +-- tables schema after running repack +-- +\d tbl_cluster + Table "public.tbl_cluster" + Column | Type | Modifiers +--------+-----------------------------+----------- + col1 | integer | not null + time | timestamp without time zone | + ,") | text | not null +Indexes: + "tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1) WITH (fillfactor='75') + ",") cluster" btree ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor='75') CLUSTER + +\d tbl_gistkey + Table "public.tbl_gistkey" + Column | Type | Modifiers +--------+---------+----------- + id | integer | not null + c | circle | +Indexes: + "tbl_gistkey_pkey" PRIMARY KEY, btree (id) + "cidx_circle" gist (c) CLUSTER + +\d tbl_only_ckey + Table "public.tbl_only_ckey" + Column | Type | Modifiers +--------+-----------------------------+----------- + col1 | integer | + col2 | timestamp without time zone | + ,") | text | +Indexes: + "cidx_only_ckey" btree (col2, ","")") CLUSTER + +\d tbl_only_pkey + Table "public.tbl_only_pkey" + Column | Type | Modifiers +--------+---------+----------- + col1 | integer | not null + ,") | text | +Indexes: + "tbl_only_pkey_pkey" PRIMARY KEY, btree (col1) + +\d tbl_with_dropped_column +Table "public.tbl_with_dropped_column" + Column | Type | Modifiers +--------+---------+----------- + c1 | text | + id | integer | not null + c2 | text | + c3 | text | +Indexes: + "tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) WITH (fillfactor='75') CLUSTER + "idx_c1c2" btree (c1, c2) WITH (fillfactor='75') + "idx_c2c1" btree (c2, c1) + +\d tbl_with_dropped_toast +Table "public.tbl_with_dropped_toast" + Column | Type | Modifiers +--------+---------+----------- + i | integer | not null + j | integer | not null +Indexes: + "tbl_with_dropped_toast_pkey" PRIMARY KEY, btree (i, j) CLUSTER + +\d tbl_idxopts + Table "public.tbl_idxopts" + Column | Type | Modifiers +--------+---------+----------- + i | integer | not null + t | text | +Indexes: + "tbl_idxopts_pkey" PRIMARY KEY, btree (i) + "idxopts_t" btree (t DESC NULLS LAST) WHERE t <> 'aaa'::text + diff --git a/regress/expected/after-schema_1.out b/regress/expected/after-schema_1.out new file mode 100644 index 0000000..2bd4d74 --- /dev/null +++ b/regress/expected/after-schema_1.out @@ -0,0 +1,75 @@ +-- +-- tables schema after running repack +-- +\d tbl_cluster + Table "public.tbl_cluster" + Column | Type | Collation | Nullable | Default +--------+-----------------------------+-----------+----------+--------- + col1 | integer | | not null | + time | timestamp without time zone | | | + ,") | text | | not null | +Indexes: + "tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1) WITH (fillfactor='75') + ",") cluster" btree ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor='75') CLUSTER + +\d tbl_gistkey + Table "public.tbl_gistkey" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + id | integer | | not null | + c | circle | | | +Indexes: + "tbl_gistkey_pkey" PRIMARY KEY, btree (id) + "cidx_circle" gist (c) CLUSTER + +\d tbl_only_ckey + Table "public.tbl_only_ckey" + Column | Type | Collation | Nullable | Default +--------+-----------------------------+-----------+----------+--------- + col1 | integer | | | + col2 | timestamp without time zone | | | + ,") | text | | | +Indexes: + "cidx_only_ckey" btree (col2, ","")") CLUSTER + +\d tbl_only_pkey + Table "public.tbl_only_pkey" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + col1 | integer | | not null | + ,") | text | | | +Indexes: + "tbl_only_pkey_pkey" PRIMARY KEY, btree (col1) + +\d tbl_with_dropped_column + Table "public.tbl_with_dropped_column" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + c1 | text | | | + id | integer | | not null | + c2 | text | | | + c3 | text | | | +Indexes: + "tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) WITH (fillfactor='75') CLUSTER + "idx_c1c2" btree (c1, c2) WITH (fillfactor='75') + "idx_c2c1" btree (c2, c1) + +\d tbl_with_dropped_toast + Table "public.tbl_with_dropped_toast" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + i | integer | | not null | + j | integer | | not null | +Indexes: + "tbl_with_dropped_toast_pkey" PRIMARY KEY, btree (i, j) CLUSTER + +\d tbl_idxopts + Table "public.tbl_idxopts" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + i | integer | | not null | + t | text | | | +Indexes: + "tbl_idxopts_pkey" PRIMARY KEY, btree (i) + "idxopts_t" btree (t DESC NULLS LAST) WHERE t <> 'aaa'::text + diff --git a/regress/expected/issue3.out b/regress/expected/issue3.out index ee3e9a7..edb2862 100644 --- a/regress/expected/issue3.out +++ b/regress/expected/issue3.out @@ -10,7 +10,7 @@ SELECT repack.get_order_by('issue3_1_idx'::regclass::oid, 'issue3_1'::regclass:: (1 row) \! pg_repack --dbname=contrib_regression --table=issue3_1 -INFO: repacking table "issue3_1" +INFO: repacking table "public.issue3_1" CREATE TABLE issue3_2 (col1 int NOT NULL, col2 text NOT NULL); CREATE UNIQUE INDEX issue3_2_idx ON issue3_2 (col1 DESC, col2 text_pattern_ops); SELECT repack.get_order_by('issue3_2_idx'::regclass::oid, 'issue3_2'::regclass::oid); @@ -20,7 +20,7 @@ SELECT repack.get_order_by('issue3_2_idx'::regclass::oid, 'issue3_2'::regclass:: (1 row) \! pg_repack --dbname=contrib_regression --table=issue3_2 -INFO: repacking table "issue3_2" +INFO: repacking table "public.issue3_2" CREATE TABLE issue3_3 (col1 int NOT NULL, col2 text NOT NULL); CREATE UNIQUE INDEX issue3_3_idx ON issue3_3 (col1 DESC, col2 DESC); SELECT repack.get_order_by('issue3_3_idx'::regclass::oid, 'issue3_3'::regclass::oid); @@ -30,7 +30,7 @@ SELECT repack.get_order_by('issue3_3_idx'::regclass::oid, 'issue3_3'::regclass:: (1 row) \! pg_repack --dbname=contrib_regression --table=issue3_3 -INFO: repacking table "issue3_3" +INFO: repacking table "public.issue3_3" CREATE TABLE issue3_4 (col1 int NOT NULL, col2 text NOT NULL); CREATE UNIQUE INDEX issue3_4_idx ON issue3_4 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST); SELECT repack.get_order_by('issue3_4_idx'::regclass::oid, 'issue3_4'::regclass::oid); @@ -40,7 +40,7 @@ SELECT repack.get_order_by('issue3_4_idx'::regclass::oid, 'issue3_4'::regclass:: (1 row) \! pg_repack --dbname=contrib_regression --table=issue3_4 -INFO: repacking table "issue3_4" +INFO: repacking table "public.issue3_4" CREATE TABLE issue3_5 (col1 int NOT NULL, col2 text NOT NULL); CREATE UNIQUE INDEX issue3_5_idx ON issue3_5 (col1 DESC NULLS FIRST, col2 COLLATE "POSIX" DESC); SELECT repack.get_order_by('issue3_5_idx'::regclass::oid, 'issue3_5'::regclass::oid); @@ -50,4 +50,4 @@ SELECT repack.get_order_by('issue3_5_idx'::regclass::oid, 'issue3_5'::regclass:: (1 row) \! pg_repack --dbname=contrib_regression --table=issue3_5 -INFO: repacking table "issue3_5" +INFO: repacking table "public.issue3_5" diff --git a/regress/expected/nosuper.out b/regress/expected/nosuper.out new file mode 100644 index 0000000..1d2fad2 --- /dev/null +++ b/regress/expected/nosuper.out @@ -0,0 +1,19 @@ +-- +-- no superuser check +-- +SET client_min_messages = error; +DROP ROLE IF EXISTS nosuper; +SET client_min_messages = warning; +CREATE ROLE nosuper WITH LOGIN; +-- => OK +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check +INFO: repacking table "public.tbl_cluster" +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper +ERROR: pg_repack failed with error: You must be a superuser to use pg_repack +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check +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; diff --git a/regress/expected/nosuper_1.out b/regress/expected/nosuper_1.out new file mode 100644 index 0000000..973ab29 --- /dev/null +++ b/regress/expected/nosuper_1.out @@ -0,0 +1,17 @@ +-- +-- no superuser check +-- +SET client_min_messages = error; +DROP ROLE IF EXISTS nosuper; +SET client_min_messages = warning; +CREATE ROLE nosuper WITH LOGIN; +-- => OK +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check +INFO: repacking table "public.tbl_cluster" +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper +ERROR: pg_repack failed with error: You must be a superuser to use pg_repack +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check +ERROR: pg_repack failed with error: ERROR: permission denied for schema repack +DROP ROLE IF EXISTS nosuper; diff --git a/regress/expected/repack_1.out b/regress/expected/repack-check.out similarity index 61% rename from regress/expected/repack_1.out rename to regress/expected/repack-check.out index 98360ee..0da1133 100644 --- a/regress/expected/repack_1.out +++ b/regress/expected/repack-check.out @@ -1,226 +1,4 @@ SET client_min_messages = warning; --- --- create table. --- -CREATE TABLE tbl_cluster ( - col1 int, - "time" timestamp, - ","")" text, - PRIMARY KEY (","")", col1) WITH (fillfactor = 75) -) WITH (fillfactor = 70); -CREATE INDEX ","") cluster" ON tbl_cluster ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75); -ALTER TABLE tbl_cluster CLUSTER ON ","") cluster"; -CREATE TABLE tbl_only_pkey ( - col1 int PRIMARY KEY, - ","")" text -); -CREATE TABLE tbl_only_ckey ( - col1 int, - col2 timestamp, - ","")" text -) WITH (fillfactor = 70); -CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")"); -ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey; -CREATE TABLE tbl_gistkey ( - id integer PRIMARY KEY, - c circle -); -CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); -ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; -CREATE TABLE tbl_with_dropped_column ( - d1 text, - c1 text, - id integer PRIMARY KEY, - d2 text, - c2 text, - d3 text -); -ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75); -ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey; -CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75); -CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1); -CREATE TABLE tbl_with_dropped_toast ( - i integer, - j integer, - t text, - PRIMARY KEY (i, j) -); -ALTER TABLE tbl_with_dropped_toast CLUSTER ON tbl_with_dropped_toast_pkey; -CREATE TABLE tbl_badindex ( - id integer PRIMARY KEY, - n integer -); -CREATE TABLE tbl_idxopts ( - i integer PRIMARY KEY, - t text -); -CREATE INDEX idxopts_t ON tbl_idxopts (t DESC NULLS LAST) WHERE (t != 'aaa'); --- Use this table to play with attribute options too -ALTER TABLE tbl_idxopts ALTER i SET STATISTICS 1; -ALTER TABLE tbl_idxopts ALTER t SET (n_distinct = -0.5); -CREATE TABLE tbl_with_toast ( - i integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_toast SET (AUTOVACUUM_VACUUM_SCALE_FACTOR = 30, AUTOVACUUM_VACUUM_THRESHOLD = 300); -ALTER TABLE tbl_with_toast SET (TOAST.AUTOVACUUM_VACUUM_SCALE_FACTOR = 40, TOAST.AUTOVACUUM_VACUUM_THRESHOLD = 400); -CREATE TABLE tbl_with_mod_column_storage ( - id integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_mod_column_storage ALTER c SET STORAGE MAIN; --- --- insert data --- -INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); -INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); -INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); -INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); -INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); -INSERT INTO tbl_only_pkey VALUES(1, 'abc'); -INSERT INTO tbl_only_pkey VALUES(2, 'def'); -INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); -INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); -INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); -INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 2, 'd2', 'c2', 'd3'); -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 1, 'd2', 'c2', 'd3'); -ALTER TABLE tbl_with_dropped_column DROP COLUMN d1; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d2; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d3; -ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text; -CREATE VIEW view_for_dropped_column AS - SELECT * FROM tbl_with_dropped_column; -INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc'); -INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); -ALTER TABLE tbl_with_dropped_toast DROP COLUMN t; -INSERT INTO tbl_badindex VALUES(1, 10); -INSERT INTO tbl_badindex VALUES(2, 10); --- insert data that is always stored into the toast table if column type is extended. -INSERT INTO tbl_with_mod_column_storage SELECT 1, array_to_string(ARRAY(SELECT chr(code) FROM generate_series(33,3000) code), ''); --- This will fail. Silence the message as it's different across PG versions. -SET client_min_messages = fatal; -CREATE UNIQUE INDEX CONCURRENTLY idx_badindex_n ON tbl_badindex (n); -SET client_min_messages = warning; -INSERT INTO tbl_idxopts VALUES (0, 'abc'), (1, 'aaa'), (2, NULL), (3, 'bbb'); --- --- before --- -SELECT * FROM tbl_with_dropped_column; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM view_for_dropped_column; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM tbl_with_dropped_toast; - i | j ----+---- - 1 | 10 - 2 | 20 -(2 rows) - --- --- do repack --- -\! pg_repack --dbname=contrib_regression --table=tbl_cluster -INFO: repacking table "tbl_cluster" -\! pg_repack --dbname=contrib_regression --table=tbl_badindex -INFO: repacking table "tbl_badindex" -WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) -\! pg_repack --dbname=contrib_regression -INFO: repacking table "tbl_cluster" -INFO: repacking table "tbl_only_pkey" -INFO: repacking table "tbl_gistkey" -INFO: repacking table "tbl_with_dropped_column" -INFO: repacking table "tbl_with_dropped_toast" -INFO: repacking table "tbl_badindex" -WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) -INFO: repacking table "tbl_idxopts" -INFO: repacking table "tbl_with_toast" -INFO: repacking table "tbl_with_mod_column_storage" --- --- after --- -\d tbl_cluster - Table "public.tbl_cluster" - Column | Type | Modifiers ---------+-----------------------------+----------- - col1 | integer | not null - time | timestamp without time zone | - ,") | text | not null -Indexes: - "tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1) WITH (fillfactor='75') - ",") cluster" btree ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor='75') CLUSTER - -\d tbl_gistkey - Table "public.tbl_gistkey" - Column | Type | Modifiers ---------+---------+----------- - id | integer | not null - c | circle | -Indexes: - "tbl_gistkey_pkey" PRIMARY KEY, btree (id) - "cidx_circle" gist (c) CLUSTER - -\d tbl_only_ckey - Table "public.tbl_only_ckey" - Column | Type | Modifiers ---------+-----------------------------+----------- - col1 | integer | - col2 | timestamp without time zone | - ,") | text | -Indexes: - "cidx_only_ckey" btree (col2, ","")") CLUSTER - -\d tbl_only_pkey - Table "public.tbl_only_pkey" - Column | Type | Modifiers ---------+---------+----------- - col1 | integer | not null - ,") | text | -Indexes: - "tbl_only_pkey_pkey" PRIMARY KEY, btree (col1) - -\d tbl_with_dropped_column -Table "public.tbl_with_dropped_column" - Column | Type | Modifiers ---------+---------+----------- - c1 | text | - id | integer | not null - c2 | text | - c3 | text | -Indexes: - "tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) WITH (fillfactor='75') CLUSTER - "idx_c1c2" btree (c1, c2) WITH (fillfactor='75') - "idx_c2c1" btree (c2, c1) - -\d tbl_with_dropped_toast -Table "public.tbl_with_dropped_toast" - Column | Type | Modifiers ---------+---------+----------- - i | integer | not null - j | integer | not null -Indexes: - "tbl_with_dropped_toast_pkey" PRIMARY KEY, btree (i, j) CLUSTER - -\d tbl_idxopts - Table "public.tbl_idxopts" - Column | Type | Modifiers ---------+---------+----------- - i | integer | not null - t | text | -Indexes: - "tbl_idxopts_pkey" PRIMARY KEY, btree (i) - "idxopts_t" btree (t DESC NULLS LAST) WHERE t <> 'aaa'::text - SELECT col1, to_char("time", 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster ORDER BY 1, 2; col1 | to_char | ,") ------+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -257,8 +35,8 @@ SET enable_indexscan = off; SELECT * FROM tbl_with_dropped_column ; c1 | id | c2 | c3 ----+----+----+---- - c1 | 2 | c2 | c1 | 1 | c2 | + c1 | 2 | c2 | (2 rows) SELECT * FROM view_for_dropped_column ORDER BY 1, 2; @@ -287,8 +65,8 @@ SELECT * FROM tbl_with_dropped_column ORDER BY 1, 2; SELECT * FROM view_for_dropped_column; c1 | id | c2 | c3 ----+----+----+---- - c1 | 2 | c2 | c1 | 1 | c2 | + c1 | 2 | c2 | (2 rows) SELECT * FROM tbl_with_dropped_toast; @@ -363,24 +141,24 @@ CREATE TABLE tbl_pk_uk (col1 int NOT NULL, col2 int NOT NULL, PRIMARY KEY(col1, CREATE TABLE tbl_nn_puk (col1 int NOT NULL, col2 int NOT NULL); CREATE UNIQUE INDEX tbl_nn_puk_pcol1_idx ON tbl_nn_puk(col1) WHERE col1 < 10; \! pg_repack --dbname=contrib_regression --table=tbl_nn -WARNING: relation "tbl_nn" must have a primary key or not-null unique keys +WARNING: relation "public.tbl_nn" must have a primary key or not-null unique keys -- => WARNING \! pg_repack --dbname=contrib_regression --table=tbl_uk -WARNING: relation "tbl_uk" must have a primary key or not-null unique keys +WARNING: relation "public.tbl_uk" must have a primary key or not-null unique keys -- => WARNING \! pg_repack --dbname=contrib_regression --table=tbl_nn_uk -INFO: repacking table "tbl_nn_uk" +INFO: repacking table "public.tbl_nn_uk" -- => OK \! pg_repack --dbname=contrib_regression --table=tbl_pk_uk -INFO: repacking table "tbl_pk_uk" +INFO: repacking table "public.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_col2_col1_key" -INFO: repacking index "public"."tbl_pk_uk_pkey" +INFO: repacking index "public.tbl_pk_uk_col2_col1_key" +INFO: repacking index "public.tbl_pk_uk_pkey" -- => 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 +WARNING: relation "public.tbl_nn_puk" must have a primary key or not-null unique keys -- => WARNING -- -- Triggers handling @@ -391,23 +169,62 @@ LANGUAGE plpgsql; CREATE TABLE trg1 (id integer PRIMARY KEY); CREATE TRIGGER repack_trigger_1 AFTER UPDATE ON trg1 FOR EACH ROW EXECUTE PROCEDURE trgtest(); \! pg_repack --dbname=contrib_regression --table=trg1 -INFO: repacking table "trg1" +INFO: repacking table "public.trg1" CREATE TABLE trg2 (id integer PRIMARY KEY); CREATE TRIGGER repack_trigger AFTER UPDATE ON trg2 FOR EACH ROW EXECUTE PROCEDURE trgtest(); \! pg_repack --dbname=contrib_regression --table=trg2 -INFO: repacking table "trg2" -WARNING: the table "trg2" already has a trigger called "repack_trigger" +INFO: repacking table "public.trg2" +WARNING: the table "public.trg2" already has a trigger called "repack_trigger" DETAIL: The trigger was probably installed during a previous attempt to run pg_repack on the table which was interrupted and for some reason failed to clean up the temporary objects. Please drop the trigger or drop and recreate the pg_repack extension altogether to remove all the temporary objects left over. CREATE TABLE trg3 (id integer PRIMARY KEY); CREATE TRIGGER repack_trigger_1 BEFORE UPDATE ON trg3 FOR EACH ROW EXECUTE PROCEDURE trgtest(); \! pg_repack --dbname=contrib_regression --table=trg3 -INFO: repacking table "trg3" +INFO: repacking table "public.trg3" +-- +-- Table re-organization using specific column +-- +-- reorganize table using cluster key. Sort in ascending order. +\! pg_repack --dbname=contrib_regression --table=tbl_order +INFO: repacking table "public.tbl_order" +SELECT ctid, c FROM tbl_order WHERE ctid <= '(0,10)'; + ctid | c +--------+---- + (0,1) | 1 + (0,2) | 2 + (0,3) | 3 + (0,4) | 4 + (0,5) | 5 + (0,6) | 6 + (0,7) | 7 + (0,8) | 8 + (0,9) | 9 + (0,10) | 10 +(10 rows) + +-- reorganize table using specific column order. Sort in descending order. +\! pg_repack --dbname=contrib_regression --table=tbl_order -o "c DESC" +INFO: repacking table "public.tbl_order" +SELECT ctid, c FROM tbl_order WHERE ctid <= '(0,10)'; + ctid | c +--------+----- + (0,1) | 100 + (0,2) | 99 + (0,3) | 98 + (0,4) | 97 + (0,5) | 96 + (0,6) | 95 + (0,7) | 94 + (0,8) | 93 + (0,9) | 92 + (0,10) | 91 +(10 rows) + -- -- Dry run -- \! pg_repack --dbname=contrib_regression --table=tbl_cluster --dry-run INFO: Dry run enabled, not executing repack -INFO: repacking table "tbl_cluster" +INFO: repacking table "public.tbl_cluster" -- Test --schema -- CREATE SCHEMA test_schema1; @@ -436,22 +253,7 @@ ERROR: cannot repack specific schema(s) in all databases -- don't kill backend -- \! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-kill-backend -INFO: repacking table "tbl_cluster" --- --- no superuser check --- -DROP ROLE IF EXISTS nosuper; -CREATE ROLE nosuper WITH LOGIN; --- => OK -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check -INFO: repacking table "tbl_cluster" --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper -ERROR: pg_repack failed with error: You must be a superuser to use pg_repack --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check -ERROR: pg_repack failed with error: ERROR: permission denied for schema repack -DROP ROLE IF EXISTS nosuper; +INFO: repacking table "public.tbl_cluster" -- -- exclude extension check -- @@ -495,39 +297,39 @@ ERROR: cannot repack specific table(s) in schema, use schema.table notation inst ERROR: cannot repack specific table(s) in all databases -- => OK \! pg_repack --dbname=contrib_regression --table=parent_a --parent-table=parent_b -INFO: repacking table "parent_a" -INFO: repacking table "parent_b" -INFO: repacking table "child_b_1" -INFO: repacking table "child_b_2" +INFO: repacking table "public.child_b_1" +INFO: repacking table "public.child_b_2" +INFO: repacking table "public.parent_a" +INFO: repacking table "public.parent_b" -- => OK \! pg_repack --dbname=contrib_regression --parent-table=parent_a --parent-table=parent_b -INFO: repacking table "parent_a" -INFO: repacking table "child_a_1" -INFO: repacking table "child_a_2" -INFO: repacking table "parent_b" -INFO: repacking table "child_b_1" -INFO: repacking table "child_b_2" +INFO: repacking table "public.child_a_1" +INFO: repacking table "public.child_a_2" +INFO: repacking table "public.child_b_1" +INFO: repacking table "public.child_b_2" +INFO: repacking table "public.parent_a" +INFO: repacking table "public.parent_b" -- => OK \! pg_repack --dbname=contrib_regression --table=parent_a --parent-table=parent_b --only-indexes INFO: repacking indexes of "parent_a" -INFO: repacking index "public"."parent_a_pkey" +INFO: repacking index "public.parent_a_pkey" INFO: repacking indexes of "public.child_b_1" -INFO: repacking index "public"."child_b_1_pkey" +INFO: repacking index "public.child_b_1_pkey" INFO: repacking indexes of "public.child_b_2" -INFO: repacking index "public"."child_b_2_pkey" +INFO: repacking index "public.child_b_2_pkey" INFO: repacking indexes of "public.parent_b" -INFO: repacking index "public"."parent_b_pkey" +INFO: repacking index "public.parent_b_pkey" -- => OK \! pg_repack --dbname=contrib_regression --parent-table=parent_a --parent-table=parent_b --only-indexes INFO: repacking indexes of "public.child_a_1" -INFO: repacking index "public"."child_a_1_pkey" +INFO: repacking index "public.child_a_1_pkey" INFO: repacking indexes of "public.child_a_2" -INFO: repacking index "public"."child_a_2_pkey" +INFO: repacking index "public.child_a_2_pkey" INFO: repacking indexes of "public.parent_a" -INFO: repacking index "public"."parent_a_pkey" +INFO: repacking index "public.parent_a_pkey" INFO: repacking indexes of "public.child_b_1" -INFO: repacking index "public"."child_b_1_pkey" +INFO: repacking index "public.child_b_1_pkey" INFO: repacking indexes of "public.child_b_2" -INFO: repacking index "public"."child_b_2_pkey" +INFO: repacking index "public.child_b_2_pkey" INFO: repacking indexes of "public.parent_b" -INFO: repacking index "public"."parent_b_pkey" +INFO: repacking index "public.parent_b_pkey" diff --git a/regress/expected/repack-run.out b/regress/expected/repack-run.out new file mode 100644 index 0000000..032e47a --- /dev/null +++ b/regress/expected/repack-run.out @@ -0,0 +1,20 @@ +-- +-- do repack +-- +\! pg_repack --dbname=contrib_regression --table=tbl_cluster +INFO: repacking table "public.tbl_cluster" +\! pg_repack --dbname=contrib_regression --table=tbl_badindex +INFO: repacking table "public.tbl_badindex" +WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) +\! pg_repack --dbname=contrib_regression +INFO: repacking table "public.tbl_badindex" +WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) +INFO: repacking table "public.tbl_cluster" +INFO: repacking table "public.tbl_gistkey" +INFO: repacking table "public.tbl_idxopts" +INFO: repacking table "public.tbl_only_pkey" +INFO: repacking table "public.tbl_order" +INFO: repacking table "public.tbl_with_dropped_column" +INFO: repacking table "public.tbl_with_dropped_toast" +INFO: repacking table "public.tbl_with_mod_column_storage" +INFO: repacking table "public.tbl_with_toast" diff --git a/regress/expected/repack-run_1.out b/regress/expected/repack-run_1.out new file mode 100644 index 0000000..54efc7b --- /dev/null +++ b/regress/expected/repack-run_1.out @@ -0,0 +1,20 @@ +-- +-- do repack +-- +\! pg_repack --dbname=contrib_regression --table=tbl_cluster +INFO: repacking table "public.tbl_cluster" +\! pg_repack --dbname=contrib_regression --table=tbl_badindex +INFO: repacking table "public.tbl_badindex" +WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON public.tbl_badindex USING btree (n) +\! pg_repack --dbname=contrib_regression +INFO: repacking table "public.tbl_badindex" +WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON public.tbl_badindex USING btree (n) +INFO: repacking table "public.tbl_cluster" +INFO: repacking table "public.tbl_gistkey" +INFO: repacking table "public.tbl_idxopts" +INFO: repacking table "public.tbl_only_pkey" +INFO: repacking table "public.tbl_order" +INFO: repacking table "public.tbl_with_dropped_column" +INFO: repacking table "public.tbl_with_dropped_toast" +INFO: repacking table "public.tbl_with_mod_column_storage" +INFO: repacking table "public.tbl_with_toast" diff --git a/regress/expected/repack-setup.out b/regress/expected/repack-setup.out new file mode 100644 index 0000000..e9a6351 --- /dev/null +++ b/regress/expected/repack-setup.out @@ -0,0 +1,139 @@ +SET client_min_messages = warning; +-- +-- create table. +-- +CREATE TABLE tbl_cluster ( + col1 int, + "time" timestamp, + ","")" text, + PRIMARY KEY (","")", col1) WITH (fillfactor = 75) +) WITH (fillfactor = 70); +CREATE INDEX ","") cluster" ON tbl_cluster ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75); +ALTER TABLE tbl_cluster CLUSTER ON ","") cluster"; +CREATE TABLE tbl_only_pkey ( + col1 int PRIMARY KEY, + ","")" text +); +CREATE TABLE tbl_only_ckey ( + col1 int, + col2 timestamp, + ","")" text +) WITH (fillfactor = 70); +CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")"); +ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey; +CREATE TABLE tbl_gistkey ( + id integer PRIMARY KEY, + c circle +); +CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); +ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; +CREATE TABLE tbl_with_dropped_column ( + d1 text, + c1 text, + id integer PRIMARY KEY, + d2 text, + c2 text, + d3 text +); +ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75); +ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey; +CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75); +CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1); +CREATE TABLE tbl_with_dropped_toast ( + i integer, + j integer, + t text, + PRIMARY KEY (i, j) +); +ALTER TABLE tbl_with_dropped_toast CLUSTER ON tbl_with_dropped_toast_pkey; +CREATE TABLE tbl_badindex ( + id integer PRIMARY KEY, + n integer +); +CREATE TABLE tbl_idxopts ( + i integer PRIMARY KEY, + t text +); +CREATE INDEX idxopts_t ON tbl_idxopts (t DESC NULLS LAST) WHERE (t != 'aaa'); +-- Use this table to play with attribute options too +ALTER TABLE tbl_idxopts ALTER i SET STATISTICS 1; +ALTER TABLE tbl_idxopts ALTER t SET (n_distinct = -0.5); +CREATE TABLE tbl_with_toast ( + i integer PRIMARY KEY, + c text +); +ALTER TABLE tbl_with_toast SET (AUTOVACUUM_VACUUM_SCALE_FACTOR = 30, AUTOVACUUM_VACUUM_THRESHOLD = 300); +ALTER TABLE tbl_with_toast SET (TOAST.AUTOVACUUM_VACUUM_SCALE_FACTOR = 40, TOAST.AUTOVACUUM_VACUUM_THRESHOLD = 400); +CREATE TABLE tbl_with_mod_column_storage ( + id integer PRIMARY KEY, + c text +); +ALTER TABLE tbl_with_mod_column_storage ALTER c SET STORAGE MAIN; +CREATE TABLE tbl_order (c int primary key); +-- +-- insert data +-- +INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); +INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); +INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); +INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); +INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); +INSERT INTO tbl_only_pkey VALUES(1, 'abc'); +INSERT INTO tbl_only_pkey VALUES(2, 'def'); +INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); +INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); +INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); +INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); +INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 2, 'd2', 'c2', 'd3'); +INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 1, 'd2', 'c2', 'd3'); +ALTER TABLE tbl_with_dropped_column DROP COLUMN d1; +ALTER TABLE tbl_with_dropped_column DROP COLUMN d2; +ALTER TABLE tbl_with_dropped_column DROP COLUMN d3; +ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text; +CREATE VIEW view_for_dropped_column AS + SELECT * FROM tbl_with_dropped_column; +INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc'); +INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); +ALTER TABLE tbl_with_dropped_toast DROP COLUMN t; +INSERT INTO tbl_badindex VALUES(1, 10); +INSERT INTO tbl_badindex VALUES(2, 10); +-- insert data that is always stored into the toast table if column type is extended. +SELECT setseed(0); INSERT INTO tbl_with_mod_column_storage SELECT 1, array_to_string(ARRAY(SELECT chr((random() * (127 - 32) + 32)::int) FROM generate_series(1, 3 * 1024) code), ''); + setseed +--------- + +(1 row) + +-- This will fail. Silence the message as it's different across PG versions. +SET client_min_messages = fatal; +CREATE UNIQUE INDEX CONCURRENTLY idx_badindex_n ON tbl_badindex (n); +SET client_min_messages = warning; +INSERT INTO tbl_idxopts VALUES (0, 'abc'), (1, 'aaa'), (2, NULL), (3, 'bbb'); +-- Insert no-ordered data +INSERT INTO tbl_order SELECT generate_series(100, 51, -1); +CLUSTER tbl_order USING tbl_order_pkey; +INSERT INTO tbl_order SELECT generate_series(50, 1, -1); +-- +-- before +-- +SELECT * FROM tbl_with_dropped_column; + c1 | id | c2 | c3 +----+----+----+---- + c1 | 2 | c2 | + c1 | 1 | c2 | +(2 rows) + +SELECT * FROM view_for_dropped_column; + c1 | id | c2 | c3 +----+----+----+---- + c1 | 2 | c2 | + c1 | 1 | c2 | +(2 rows) + +SELECT * FROM tbl_with_dropped_toast; + i | j +---+---- + 1 | 10 + 2 | 20 +(2 rows) + diff --git a/regress/expected/repack.out b/regress/expected/repack.out deleted file mode 100644 index 5934f65..0000000 --- a/regress/expected/repack.out +++ /dev/null @@ -1,535 +0,0 @@ -SET client_min_messages = warning; --- --- create table. --- -CREATE TABLE tbl_cluster ( - col1 int, - "time" timestamp, - ","")" text, - PRIMARY KEY (","")", col1) WITH (fillfactor = 75) -) WITH (fillfactor = 70); -CREATE INDEX ","") cluster" ON tbl_cluster ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75); -ALTER TABLE tbl_cluster CLUSTER ON ","") cluster"; -CREATE TABLE tbl_only_pkey ( - col1 int PRIMARY KEY, - ","")" text -); -CREATE TABLE tbl_only_ckey ( - col1 int, - col2 timestamp, - ","")" text -) WITH (fillfactor = 70); -CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")"); -ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey; -CREATE TABLE tbl_gistkey ( - id integer PRIMARY KEY, - c circle -); -CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); -ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; -CREATE TABLE tbl_with_dropped_column ( - d1 text, - c1 text, - id integer PRIMARY KEY, - d2 text, - c2 text, - d3 text -); -ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75); -ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey; -CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75); -CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1); -CREATE TABLE tbl_with_dropped_toast ( - i integer, - j integer, - t text, - PRIMARY KEY (i, j) -); -ALTER TABLE tbl_with_dropped_toast CLUSTER ON tbl_with_dropped_toast_pkey; -CREATE TABLE tbl_badindex ( - id integer PRIMARY KEY, - n integer -); -CREATE TABLE tbl_idxopts ( - i integer PRIMARY KEY, - t text -); -CREATE INDEX idxopts_t ON tbl_idxopts (t DESC NULLS LAST) WHERE (t != 'aaa'); --- Use this table to play with attribute options too -ALTER TABLE tbl_idxopts ALTER i SET STATISTICS 1; -ALTER TABLE tbl_idxopts ALTER t SET (n_distinct = -0.5); -CREATE TABLE tbl_with_toast ( - i integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_toast SET (AUTOVACUUM_VACUUM_SCALE_FACTOR = 30, AUTOVACUUM_VACUUM_THRESHOLD = 300); -ALTER TABLE tbl_with_toast SET (TOAST.AUTOVACUUM_VACUUM_SCALE_FACTOR = 40, TOAST.AUTOVACUUM_VACUUM_THRESHOLD = 400); -CREATE TABLE tbl_with_mod_column_storage ( - id integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_mod_column_storage ALTER c SET STORAGE MAIN; --- --- insert data --- -INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); -INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); -INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); -INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); -INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); -INSERT INTO tbl_only_pkey VALUES(1, 'abc'); -INSERT INTO tbl_only_pkey VALUES(2, 'def'); -INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); -INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); -INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); -INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 2, 'd2', 'c2', 'd3'); -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 1, 'd2', 'c2', 'd3'); -ALTER TABLE tbl_with_dropped_column DROP COLUMN d1; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d2; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d3; -ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text; -CREATE VIEW view_for_dropped_column AS - SELECT * FROM tbl_with_dropped_column; -INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc'); -INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); -ALTER TABLE tbl_with_dropped_toast DROP COLUMN t; -INSERT INTO tbl_badindex VALUES(1, 10); -INSERT INTO tbl_badindex VALUES(2, 10); --- insert data that is always stored into the toast table if column type is extended. -INSERT INTO tbl_with_mod_column_storage SELECT 1, array_to_string(ARRAY(SELECT chr(code) FROM generate_series(33,3000) code), ''); --- This will fail. Silence the message as it's different across PG versions. -SET client_min_messages = fatal; -CREATE UNIQUE INDEX CONCURRENTLY idx_badindex_n ON tbl_badindex (n); -SET client_min_messages = warning; -INSERT INTO tbl_idxopts VALUES (0, 'abc'), (1, 'aaa'), (2, NULL), (3, 'bbb'); --- --- before --- -SELECT * FROM tbl_with_dropped_column; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM view_for_dropped_column; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM tbl_with_dropped_toast; - i | j ----+---- - 1 | 10 - 2 | 20 -(2 rows) - --- --- do repack --- -\! pg_repack --dbname=contrib_regression --table=tbl_cluster -INFO: repacking table "tbl_cluster" -\! pg_repack --dbname=contrib_regression --table=tbl_badindex -INFO: repacking table "tbl_badindex" -WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) -\! pg_repack --dbname=contrib_regression -INFO: repacking table "tbl_cluster" -INFO: repacking table "tbl_only_pkey" -INFO: repacking table "tbl_gistkey" -INFO: repacking table "tbl_with_dropped_column" -INFO: repacking table "tbl_with_dropped_toast" -INFO: repacking table "tbl_badindex" -WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n) -INFO: repacking table "tbl_idxopts" -INFO: repacking table "tbl_with_toast" -INFO: repacking table "tbl_with_mod_column_storage" --- --- after --- -\d tbl_cluster - Table "public.tbl_cluster" - Column | Type | Modifiers ---------+-----------------------------+----------- - col1 | integer | not null - time | timestamp without time zone | - ,") | text | not null -Indexes: - "tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1) WITH (fillfactor='75') - ",") cluster" btree ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor='75') CLUSTER - -\d tbl_gistkey - Table "public.tbl_gistkey" - Column | Type | Modifiers ---------+---------+----------- - id | integer | not null - c | circle | -Indexes: - "tbl_gistkey_pkey" PRIMARY KEY, btree (id) - "cidx_circle" gist (c) CLUSTER - -\d tbl_only_ckey - Table "public.tbl_only_ckey" - Column | Type | Modifiers ---------+-----------------------------+----------- - col1 | integer | - col2 | timestamp without time zone | - ,") | text | -Indexes: - "cidx_only_ckey" btree (col2, ","")") CLUSTER - -\d tbl_only_pkey - Table "public.tbl_only_pkey" - Column | Type | Modifiers ---------+---------+----------- - col1 | integer | not null - ,") | text | -Indexes: - "tbl_only_pkey_pkey" PRIMARY KEY, btree (col1) - -\d tbl_with_dropped_column -Table "public.tbl_with_dropped_column" - Column | Type | Modifiers ---------+---------+----------- - c1 | text | - id | integer | not null - c2 | text | - c3 | text | -Indexes: - "tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) WITH (fillfactor='75') CLUSTER - "idx_c1c2" btree (c1, c2) WITH (fillfactor='75') - "idx_c2c1" btree (c2, c1) - -\d tbl_with_dropped_toast -Table "public.tbl_with_dropped_toast" - Column | Type | Modifiers ---------+---------+----------- - i | integer | not null - j | integer | not null -Indexes: - "tbl_with_dropped_toast_pkey" PRIMARY KEY, btree (i, j) CLUSTER - -\d tbl_idxopts - Table "public.tbl_idxopts" - Column | Type | Modifiers ---------+---------+----------- - i | integer | not null - t | text | -Indexes: - "tbl_idxopts_pkey" PRIMARY KEY, btree (i) - "idxopts_t" btree (t DESC NULLS LAST) WHERE t <> 'aaa'::text - -SELECT col1, to_char("time", 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster ORDER BY 1, 2; - col1 | to_char | ,") -------+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - 1 | 2008-12-31 10:00:00 | admin - 2 | 2008-01-01 00:00:00 | king - 3 | 2008-03-04 12:00:00 | joker - 4 | 2008-03-05 15:00:00 | queen - 5 | 2008-01-01 00:30:00 | 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457502877599617298355752203375318570113543746034084988471603868999706990048150305440277903164542478230684929369186215805784631115966687130130156185689872372352885092648612494977154218334204285686060146824720771435854874155657069677653720226485447015858801620758474922657226002085584466521458398893944370926591800311388246468157082630100594858704003186480342194897278290641045072636881313739855256117322040245091227700226941127573627280495738108967504018369868368450725799364729060762996941380475654823728997180326802474420629269124859052181004459842150591120249441341728531478105803603371077309182869314710171111683916581726889419758716582152128229518488471.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146186757248575675626141415406703029969945094998952478811655512094373648528093231902305582067974820101084674923265015312343266903322886650672254668921837971227047131660367861588019049986537379859389467650347506576050756618348129606100947602187190325083145829523959832997789824508288714463832917347224163984587855397667958063818353666110843173780894378316102088305524901670023520711144288695990956365797087168498072899493296484283020786408603988738697537582317317831395992983007838702877053913369563312103707264019249106768231199288375641141422016742752102372994270831059898459475987664288897796147837958390228854852903576033852808064381972344661059689722872865264153822664698420021195484155278441181286534507035191650016689294415480846071277143999762926834629577438361895110127148638746976545982451788550975379013880664961911962222957110555242923723192197738262561631468842032853716682938649611917049738836395495938 -(5 rows) - -SELECT * FROM tbl_only_ckey ORDER BY 1; - col1 | col2 | ,") -------+--------------------------+----- - 1 | Tue Jan 01 00:00:00 2008 | abc - 2 | Fri Feb 01 00:00:00 2008 | def -(2 rows) - -SELECT * FROM tbl_only_pkey ORDER BY 1; - col1 | ,") -------+----- - 1 | abc - 2 | def -(2 rows) - -SELECT * FROM tbl_gistkey ORDER BY 1; - id | c -----+----------- - 1 | <(1,2),3> - 2 | <(4,5),6> -(2 rows) - -SET enable_seqscan = on; -SET enable_indexscan = off; -SELECT * FROM tbl_with_dropped_column ; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM view_for_dropped_column ORDER BY 1, 2; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 1 | c2 | - c1 | 2 | c2 | -(2 rows) - -SELECT * FROM tbl_with_dropped_toast; - i | j ----+---- - 1 | 10 - 2 | 20 -(2 rows) - -SET enable_seqscan = off; -SET enable_indexscan = on; -SELECT * FROM tbl_with_dropped_column ORDER BY 1, 2; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 1 | c2 | - c1 | 2 | c2 | -(2 rows) - -SELECT * FROM view_for_dropped_column; - c1 | id | c2 | c3 -----+----+----+---- - c1 | 2 | c2 | - c1 | 1 | c2 | -(2 rows) - -SELECT * FROM tbl_with_dropped_toast; - i | j ----+---- - 1 | 10 - 2 | 20 -(2 rows) - -RESET enable_seqscan; -RESET enable_indexscan; --- check if storage option for both table and TOAST table didn't go away. -SELECT CASE relkind - WHEN 'r' THEN relname - WHEN 't' THEN 'toast_table' - END as table, - reloptions -FROM pg_class -WHERE relname = 'tbl_with_toast' OR relname = 'pg_toast_' || 'tbl_with_toast'::regclass::oid -ORDER BY 1; - table | reloptions -----------------+--------------------------------------------------------------------- - tbl_with_toast | {autovacuum_vacuum_scale_factor=30,autovacuum_vacuum_threshold=300} - toast_table | {autovacuum_vacuum_scale_factor=40,autovacuum_vacuum_threshold=400} -(2 rows) - -SELECT pg_relation_size(reltoastrelid) = 0 as check_toast_rel_size FROM pg_class WHERE relname = 'tbl_with_mod_column_storage'; - check_toast_rel_size ----------------------- - t -(1 row) - --- --- check broken links or orphan toast relations --- -SELECT oid, relname - FROM pg_class - WHERE relkind = 't' - AND oid NOT IN (SELECT reltoastrelid FROM pg_class WHERE relkind = 'r'); - oid | relname ------+--------- -(0 rows) - -SELECT oid, relname - FROM pg_class - WHERE relkind = 'r' - AND reltoastrelid <> 0 - AND reltoastrelid NOT IN (SELECT oid FROM pg_class WHERE relkind = 't'); - oid | relname ------+--------- -(0 rows) - --- check columns options -SELECT attname, attstattarget, attoptions -FROM pg_attribute -WHERE attrelid = 'tbl_idxopts'::regclass -AND attnum > 0 -ORDER BY attnum; - attname | attstattarget | attoptions ----------+---------------+------------------- - i | 1 | - t | -1 | {n_distinct=-0.5} -(2 rows) - --- --- NOT NULL UNIQUE --- -CREATE TABLE tbl_nn (col1 int NOT NULL, col2 int NOT NULL); -CREATE TABLE tbl_uk (col1 int NOT NULL, col2 int , UNIQUE(col1, col2)); -CREATE TABLE tbl_nn_uk (col1 int NOT NULL, col2 int NOT NULL, UNIQUE(col1, col2)); -CREATE TABLE tbl_pk_uk (col1 int NOT NULL, col2 int NOT NULL, PRIMARY KEY(col1, col2), UNIQUE(col2, col1)); -CREATE TABLE tbl_nn_puk (col1 int NOT NULL, col2 int NOT NULL); -CREATE UNIQUE INDEX tbl_nn_puk_pcol1_idx ON tbl_nn_puk(col1) WHERE col1 < 10; -\! pg_repack --dbname=contrib_regression --table=tbl_nn -WARNING: relation "tbl_nn" must have a primary key or not-null unique keys --- => WARNING -\! pg_repack --dbname=contrib_regression --table=tbl_uk -WARNING: relation "tbl_uk" must have a primary key or not-null unique keys --- => WARNING -\! pg_repack --dbname=contrib_regression --table=tbl_nn_uk -INFO: repacking table "tbl_nn_uk" --- => OK -\! pg_repack --dbname=contrib_regression --table=tbl_pk_uk -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_col2_col1_key" -INFO: repacking index "public"."tbl_pk_uk_pkey" --- => 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 --- => WARNING --- --- Triggers handling --- -CREATE FUNCTION trgtest() RETURNS trigger AS -$$BEGIN RETURN NEW; END$$ -LANGUAGE plpgsql; -CREATE TABLE trg1 (id integer PRIMARY KEY); -CREATE TRIGGER repack_trigger_1 AFTER UPDATE ON trg1 FOR EACH ROW EXECUTE PROCEDURE trgtest(); -\! pg_repack --dbname=contrib_regression --table=trg1 -INFO: repacking table "trg1" -CREATE TABLE trg2 (id integer PRIMARY KEY); -CREATE TRIGGER repack_trigger AFTER UPDATE ON trg2 FOR EACH ROW EXECUTE PROCEDURE trgtest(); -\! pg_repack --dbname=contrib_regression --table=trg2 -INFO: repacking table "trg2" -WARNING: the table "trg2" already has a trigger called "repack_trigger" -DETAIL: The trigger was probably installed during a previous attempt to run pg_repack on the table which was interrupted and for some reason failed to clean up the temporary objects. Please drop the trigger or drop and recreate the pg_repack extension altogether to remove all the temporary objects left over. -CREATE TABLE trg3 (id integer PRIMARY KEY); -CREATE TRIGGER repack_trigger_1 BEFORE UPDATE ON trg3 FOR EACH ROW EXECUTE PROCEDURE trgtest(); -\! pg_repack --dbname=contrib_regression --table=trg3 -INFO: repacking table "trg3" --- --- Dry run --- -\! 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_schema1.tbl1" -INFO: repacking table "test_schema1.tbl2" -INFO: repacking table "test_schema2.tbl1" -INFO: repacking table "test_schema2.tbl2" --- => 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 --- --- don't kill backend --- -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-kill-backend -INFO: repacking table "tbl_cluster" --- --- no superuser check --- -DROP ROLE IF EXISTS nosuper; -CREATE ROLE nosuper WITH LOGIN; --- => OK -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check -INFO: repacking table "tbl_cluster" --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper -ERROR: pg_repack failed with error: You must be a superuser to use pg_repack --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check -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" --- --- table inheritance check --- -CREATE TABLE parent_a(val integer primary key); -CREATE TABLE child_a_1(val integer primary key) INHERITS(parent_a); -CREATE TABLE child_a_2(val integer primary key) INHERITS(parent_a); -CREATE TABLE parent_b(val integer primary key); -CREATE TABLE child_b_1(val integer primary key) INHERITS(parent_b); -CREATE TABLE child_b_2(val integer primary key) INHERITS(parent_b); --- => ERROR -\! pg_repack --dbname=contrib_regression --parent-table=dummy_table -ERROR: pg_repack failed with error: ERROR: relation "dummy_table" does not exist --- => ERROR -\! pg_repack --dbname=contrib_regression --parent-table=dummy_index --index=dummy_index -ERROR: cannot specify --index (-i) and --parent-table (-I) --- => ERROR -\! pg_repack --dbname=contrib_regression --parent-table=dummy_table --schema=dummy_schema -ERROR: cannot repack specific table(s) in schema, use schema.table notation instead --- => ERROR -\! pg_repack --dbname=contrib_regression --parent-table=dummy_table --all -ERROR: cannot repack specific table(s) in all databases --- => OK -\! pg_repack --dbname=contrib_regression --table=parent_a --parent-table=parent_b -INFO: repacking table "parent_a" -INFO: repacking table "parent_b" -INFO: repacking table "child_b_1" -INFO: repacking table "child_b_2" --- => OK -\! pg_repack --dbname=contrib_regression --parent-table=parent_a --parent-table=parent_b -INFO: repacking table "parent_a" -INFO: repacking table "child_a_1" -INFO: repacking table "child_a_2" -INFO: repacking table "parent_b" -INFO: repacking table "child_b_1" -INFO: repacking table "child_b_2" --- => OK -\! pg_repack --dbname=contrib_regression --table=parent_a --parent-table=parent_b --only-indexes -INFO: repacking indexes of "parent_a" -INFO: repacking index "public"."parent_a_pkey" -INFO: repacking indexes of "public.child_b_1" -INFO: repacking index "public"."child_b_1_pkey" -INFO: repacking indexes of "public.child_b_2" -INFO: repacking index "public"."child_b_2_pkey" -INFO: repacking indexes of "public.parent_b" -INFO: repacking index "public"."parent_b_pkey" --- => OK -\! pg_repack --dbname=contrib_regression --parent-table=parent_a --parent-table=parent_b --only-indexes -INFO: repacking indexes of "public.child_a_1" -INFO: repacking index "public"."child_a_1_pkey" -INFO: repacking indexes of "public.child_a_2" -INFO: repacking index "public"."child_a_2_pkey" -INFO: repacking indexes of "public.parent_a" -INFO: repacking index "public"."parent_a_pkey" -INFO: repacking indexes of "public.child_b_1" -INFO: repacking index "public"."child_b_1_pkey" -INFO: repacking indexes of "public.child_b_2" -INFO: repacking index "public"."child_b_2_pkey" -INFO: repacking indexes of "public.parent_b" -INFO: repacking index "public"."parent_b_pkey" diff --git a/regress/expected/tablespace.out b/regress/expected/tablespace.out index d0e7e43..d41b31d 100644 --- a/regress/expected/tablespace.out +++ b/regress/expected/tablespace.out @@ -68,7 +68,7 @@ WHERE indrelid = 'testts1'::regclass ORDER BY relname; -- can move the tablespace from default \! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -88,7 +88,7 @@ SELECT * from testts1 order by id; -- tablespace stays where it is \! pg_repack --dbname=contrib_regression --no-order --table=testts1 -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -100,7 +100,7 @@ ORDER BY relname; -- can move the ts back to default \! pg_repack --dbname=contrib_regression --no-order --table=testts1 -s pg_default -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -111,7 +111,7 @@ ORDER BY relname; -- can move the table together with the indexes \! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts --moveidx -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -131,13 +131,13 @@ ERROR: cannot specify --moveidx (-S) without --tablespace (-s) ERROR: cannot specify --moveidx (-S) without --tablespace (-s) -- not broken with order \! pg_repack --dbname=contrib_regression -o id --table=testts1 --tablespace pg_default --moveidx -INFO: repacking table "testts1" +INFO: repacking table "public.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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -152,9 +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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -169,9 +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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -182,7 +182,7 @@ ORDER BY relname; --move one index to a tablespace \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=testts -INFO: repacking index "public"."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' @@ -194,7 +194,7 @@ ORDER BY relname; --index tablespace stays as is \! pg_repack --dbname=contrib_regression --index=testts1_pkey -INFO: repacking index "public"."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' @@ -206,7 +206,7 @@ ORDER BY relname; --move index to pg_default \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=pg_default -INFO: repacking index "public"."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' @@ -217,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 index "public"."testts1_pkey" -INFO: repacking index "public"."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/expected/tablespace_1.out b/regress/expected/tablespace_1.out index 4f7456a..0256183 100644 --- a/regress/expected/tablespace_1.out +++ b/regress/expected/tablespace_1.out @@ -68,7 +68,7 @@ WHERE indrelid = 'testts1'::regclass ORDER BY relname; -- can move the tablespace from default \! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -88,7 +88,7 @@ SELECT * from testts1 order by id; -- tablespace stays where it is \! pg_repack --dbname=contrib_regression --no-order --table=testts1 -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -100,7 +100,7 @@ ORDER BY relname; -- can move the ts back to default \! pg_repack --dbname=contrib_regression --no-order --table=testts1 -s pg_default -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -111,7 +111,7 @@ ORDER BY relname; -- can move the table together with the indexes \! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts --moveidx -INFO: repacking table "testts1" +INFO: repacking table "public.testts1" SELECT relname, spcname FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace WHERE relname ~ '^testts1' @@ -131,13 +131,13 @@ ERROR: cannot specify --moveidx (-S) without --tablespace (-s) ERROR: cannot specify --moveidx (-S) without --tablespace (-s) -- not broken with order \! pg_repack --dbname=contrib_regression -o id --table=testts1 --tablespace pg_default --moveidx -INFO: repacking table "testts1" +INFO: repacking table "public.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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -152,9 +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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -169,9 +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_partial_idx" -INFO: repacking index "public"."testts1_pkey" -INFO: repacking index "public"."testts1_with_idx" +INFO: repacking index "public.testts1_partial_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' @@ -182,7 +182,7 @@ ORDER BY relname; --move one index to a tablespace \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=testts -INFO: repacking index "public"."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' @@ -194,7 +194,7 @@ ORDER BY relname; --index tablespace stays as is \! pg_repack --dbname=contrib_regression --index=testts1_pkey -INFO: repacking index "public"."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' @@ -206,7 +206,7 @@ ORDER BY relname; --move index to pg_default \! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=pg_default -INFO: repacking index "public"."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' @@ -217,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 index "public"."testts1_pkey" -INFO: repacking index "public"."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/expected/tablespace_2.out b/regress/expected/tablespace_2.out new file mode 100644 index 0000000..e632960 --- /dev/null +++ b/regress/expected/tablespace_2.out @@ -0,0 +1,234 @@ +SET client_min_messages = warning; +-- +-- Tablespace features tests +-- +-- Note: in order to pass this test you must create a tablespace called 'testts' +-- +SELECT spcname FROM pg_tablespace WHERE spcname = 'testts'; + spcname +--------- + testts +(1 row) + +-- If the query above failed you must create the 'testts' tablespace; +CREATE TABLE testts1 (id serial primary key, data text); +CREATE INDEX testts1_partial_idx on testts1 (id) where (id > 0); +CREATE INDEX testts1_with_idx on testts1 (id) with (fillfactor=80); +INSERT INTO testts1 (data) values ('a'); +INSERT INTO testts1 (data) values ('b'); +INSERT INTO testts1 (data) values ('c'); +-- check the indexes definitions +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL, false), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +---------------------------------------------------------------------------------------------------------- + CREATE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE pg_default WHERE (id > 0) + CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE pg_default + CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor='80') TABLESPACE pg_default +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo', false), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +--------------------------------------------------------------------------------------------------- + CREATE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo WHERE (id > 0) + CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo + CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor='80') TABLESPACE foo +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL, true), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +--------------------------------------------------------------------------------------------------------------------- + CREATE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) TABLESPACE pg_default WHERE (id > 0) + CREATE UNIQUE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) TABLESPACE pg_default + CREATE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) WITH (fillfactor='80') TABLESPACE pg_default +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo', true), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +-------------------------------------------------------------------------------------------------------------- + CREATE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) TABLESPACE foo WHERE (id > 0) + CREATE UNIQUE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) TABLESPACE foo + CREATE INDEX CONCURRENTLY index_OID ON public.testts1 USING btree (id) WITH (fillfactor='80') TABLESPACE foo +(3 rows) + +-- can move the tablespace from default +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- + testts1 | testts +(1 row) + +SELECT * from testts1 order by id; + id | data +----+------ + 1 | a + 2 | b + 3 | c +(3 rows) + +-- tablespace stays where it is +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- + testts1 | testts +(1 row) + +-- can move the ts back to default +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 -s pg_default +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +-- can move the table together with the indexes +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts --moveidx +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1 | testts + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(4 rows) + +-- can't specify --moveidx without --tablespace +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --moveidx +ERROR: cannot specify --moveidx (-S) without --tablespace (-s) +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 -S +ERROR: cannot specify --moveidx (-S) without --tablespace (-s) +-- not broken with order +\! pg_repack --dbname=contrib_regression -o id --table=testts1 --tablespace pg_default --moveidx +INFO: repacking table "public.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_partial_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' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(3 rows) + +--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_partial_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' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(3 rows) + +--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_partial_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' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +--move one index to a tablespace +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=testts +INFO: repacking index "public.testts1_pkey" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +--------------+--------- + testts1_pkey | testts +(1 row) + +--index tablespace stays as is +\! pg_repack --dbname=contrib_regression --index=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' +ORDER BY relname; + relname | spcname +--------------+--------- + testts1_pkey | testts +(1 row) + +--move index to pg_default +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=pg_default +INFO: repacking index "public.testts1_pkey" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +--using multiple --index option +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --index=testts1_with_idx --tablespace=testts +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' +ORDER BY relname; + relname | spcname +------------------+--------- + testts1_pkey | testts + testts1_with_idx | testts +(2 rows) + +--using --indexes-only and --index option together +\! pg_repack --dbname=contrib_regression --table=testts1 --only-indexes --index=testts1_pkey +ERROR: cannot specify --index (-i) and --table (-t) diff --git a/regress/expected/tablespace_3.out b/regress/expected/tablespace_3.out new file mode 100644 index 0000000..bfb9d95 --- /dev/null +++ b/regress/expected/tablespace_3.out @@ -0,0 +1,234 @@ +SET client_min_messages = warning; +-- +-- Tablespace features tests +-- +-- Note: in order to pass this test you must create a tablespace called 'testts' +-- +SELECT spcname FROM pg_tablespace WHERE spcname = 'testts'; + spcname +--------- + testts +(1 row) + +-- If the query above failed you must create the 'testts' tablespace; +CREATE TABLE testts1 (id serial primary key, data text); +CREATE INDEX testts1_partial_idx on testts1 (id) where (id > 0); +CREATE INDEX testts1_with_idx on testts1 (id) with (fillfactor=80); +INSERT INTO testts1 (data) values ('a'); +INSERT INTO testts1 (data) values ('b'); +INSERT INTO testts1 (data) values ('c'); +-- check the indexes definitions +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL, false), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +---------------------------------------------------------------------------------- + CREATE INDEX index_OID ON repack.table_OID USING btree (id) WHERE (id > 0) + CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id) + CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor=80) +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo', false), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +------------------------------------------------------------------------------------------------- + CREATE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo WHERE (id > 0) + CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo + CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor=80) TABLESPACE foo +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL, true), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +-------------------------------------------------------------------------------------- + CREATE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) WHERE (id > 0) + CREATE UNIQUE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) + CREATE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) WITH (fillfactor=80) +(3 rows) + +SELECT regexp_replace( + repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo', true), + '_[0-9]+', '_OID', 'g') +FROM pg_index i join pg_class c ON c.oid = indexrelid +WHERE indrelid = 'testts1'::regclass ORDER BY relname; + regexp_replace +----------------------------------------------------------------------------------------------------- + CREATE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) TABLESPACE foo WHERE (id > 0) + CREATE UNIQUE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) TABLESPACE foo + CREATE INDEX CONCURRENTLY index_OID ON testts1 USING btree (id) WITH (fillfactor=80) TABLESPACE foo +(3 rows) + +-- can move the tablespace from default +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- + testts1 | testts +(1 row) + +SELECT * from testts1 order by id; + id | data +----+------ + 1 | a + 2 | b + 3 | c +(3 rows) + +-- tablespace stays where it is +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- + testts1 | testts +(1 row) + +-- can move the ts back to default +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 -s pg_default +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +-- can move the table together with the indexes +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts --moveidx +INFO: repacking table "public.testts1" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1 | testts + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(4 rows) + +-- can't specify --moveidx without --tablespace +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --moveidx +ERROR: cannot specify --moveidx (-S) without --tablespace (-s) +\! pg_repack --dbname=contrib_regression --no-order --table=testts1 -S +ERROR: cannot specify --moveidx (-S) without --tablespace (-s) +-- not broken with order +\! pg_repack --dbname=contrib_regression -o id --table=testts1 --tablespace pg_default --moveidx +INFO: repacking table "public.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_partial_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' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(3 rows) + +--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_partial_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' +ORDER BY relname; + relname | spcname +---------------------+--------- + testts1_partial_idx | testts + testts1_pkey | testts + testts1_with_idx | testts +(3 rows) + +--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_partial_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' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +--move one index to a tablespace +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=testts +INFO: repacking index "public.testts1_pkey" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +--------------+--------- + testts1_pkey | testts +(1 row) + +--index tablespace stays as is +\! pg_repack --dbname=contrib_regression --index=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' +ORDER BY relname; + relname | spcname +--------------+--------- + testts1_pkey | testts +(1 row) + +--move index to pg_default +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --tablespace=pg_default +INFO: repacking index "public.testts1_pkey" +SELECT relname, spcname +FROM pg_class JOIN pg_tablespace ts ON ts.oid = reltablespace +WHERE relname ~ '^testts1' +ORDER BY relname; + relname | spcname +---------+--------- +(0 rows) + +--using multiple --index option +\! pg_repack --dbname=contrib_regression --index=testts1_pkey --index=testts1_with_idx --tablespace=testts +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' +ORDER BY relname; + relname | spcname +------------------+--------- + testts1_pkey | testts + testts1_with_idx | testts +(2 rows) + +--using --indexes-only and --index option together +\! pg_repack --dbname=contrib_regression --table=testts1 --only-indexes --index=testts1_pkey +ERROR: cannot specify --index (-i) and --table (-t) diff --git a/regress/sql/after-schema.sql b/regress/sql/after-schema.sql new file mode 100644 index 0000000..161cf74 --- /dev/null +++ b/regress/sql/after-schema.sql @@ -0,0 +1,11 @@ +-- +-- tables schema after running repack +-- + +\d tbl_cluster +\d tbl_gistkey +\d tbl_only_ckey +\d tbl_only_pkey +\d tbl_with_dropped_column +\d tbl_with_dropped_toast +\d tbl_idxopts diff --git a/regress/sql/nosuper.sql b/regress/sql/nosuper.sql new file mode 100644 index 0000000..198f345 --- /dev/null +++ b/regress/sql/nosuper.sql @@ -0,0 +1,14 @@ +-- +-- no superuser check +-- +SET client_min_messages = error; +DROP ROLE IF EXISTS nosuper; +SET client_min_messages = warning; +CREATE ROLE nosuper WITH LOGIN; +-- => OK +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper +-- => ERROR +\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check +DROP ROLE IF EXISTS nosuper; diff --git a/regress/sql/repack.sql b/regress/sql/repack-check.sql similarity index 54% rename from regress/sql/repack.sql rename to regress/sql/repack-check.sql index 9f58c09..0730b1e 100644 --- a/regress/sql/repack.sql +++ b/regress/sql/repack-check.sql @@ -1,158 +1,4 @@ SET client_min_messages = warning; --- --- create table. --- -CREATE TABLE tbl_cluster ( - col1 int, - "time" timestamp, - ","")" text, - PRIMARY KEY (","")", col1) WITH (fillfactor = 75) -) WITH (fillfactor = 70); - -CREATE INDEX ","") cluster" ON tbl_cluster ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75); -ALTER TABLE tbl_cluster CLUSTER ON ","") cluster"; - -CREATE TABLE tbl_only_pkey ( - col1 int PRIMARY KEY, - ","")" text -); - -CREATE TABLE tbl_only_ckey ( - col1 int, - col2 timestamp, - ","")" text -) WITH (fillfactor = 70); - -CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")"); -ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey; - -CREATE TABLE tbl_gistkey ( - id integer PRIMARY KEY, - c circle -); - -CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); -ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; - -CREATE TABLE tbl_with_dropped_column ( - d1 text, - c1 text, - id integer PRIMARY KEY, - d2 text, - c2 text, - d3 text -); -ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75); -ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey; -CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75); -CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1); - -CREATE TABLE tbl_with_dropped_toast ( - i integer, - j integer, - t text, - PRIMARY KEY (i, j) -); -ALTER TABLE tbl_with_dropped_toast CLUSTER ON tbl_with_dropped_toast_pkey; - -CREATE TABLE tbl_badindex ( - id integer PRIMARY KEY, - n integer -); - -CREATE TABLE tbl_idxopts ( - i integer PRIMARY KEY, - t text -); -CREATE INDEX idxopts_t ON tbl_idxopts (t DESC NULLS LAST) WHERE (t != 'aaa'); - --- Use this table to play with attribute options too -ALTER TABLE tbl_idxopts ALTER i SET STATISTICS 1; -ALTER TABLE tbl_idxopts ALTER t SET (n_distinct = -0.5); -CREATE TABLE tbl_with_toast ( - i integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_toast SET (AUTOVACUUM_VACUUM_SCALE_FACTOR = 30, AUTOVACUUM_VACUUM_THRESHOLD = 300); -ALTER TABLE tbl_with_toast SET (TOAST.AUTOVACUUM_VACUUM_SCALE_FACTOR = 40, TOAST.AUTOVACUUM_VACUUM_THRESHOLD = 400); -CREATE TABLE tbl_with_mod_column_storage ( - id integer PRIMARY KEY, - c text -); -ALTER TABLE tbl_with_mod_column_storage ALTER c SET STORAGE MAIN; - --- --- insert data --- - -INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); -INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); -INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); -INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); -INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); - -INSERT INTO tbl_only_pkey VALUES(1, 'abc'); -INSERT INTO tbl_only_pkey VALUES(2, 'def'); - -INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); -INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); - -INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); -INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); - -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 2, 'd2', 'c2', 'd3'); -INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 1, 'd2', 'c2', 'd3'); -ALTER TABLE tbl_with_dropped_column DROP COLUMN d1; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d2; -ALTER TABLE tbl_with_dropped_column DROP COLUMN d3; -ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text; -CREATE VIEW view_for_dropped_column AS - SELECT * FROM tbl_with_dropped_column; - -INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc'); -INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); -ALTER TABLE tbl_with_dropped_toast DROP COLUMN t; - -INSERT INTO tbl_badindex VALUES(1, 10); -INSERT INTO tbl_badindex VALUES(2, 10); - --- insert data that is always stored into the toast table if column type is extended. -INSERT INTO tbl_with_mod_column_storage SELECT 1, array_to_string(ARRAY(SELECT chr(code) FROM generate_series(33,3000) code), ''); - --- This will fail. Silence the message as it's different across PG versions. -SET client_min_messages = fatal; -CREATE UNIQUE INDEX CONCURRENTLY idx_badindex_n ON tbl_badindex (n); -SET client_min_messages = warning; - -INSERT INTO tbl_idxopts VALUES (0, 'abc'), (1, 'aaa'), (2, NULL), (3, 'bbb'); - --- --- before --- - -SELECT * FROM tbl_with_dropped_column; -SELECT * FROM view_for_dropped_column; -SELECT * FROM tbl_with_dropped_toast; - --- --- do repack --- - -\! pg_repack --dbname=contrib_regression --table=tbl_cluster -\! pg_repack --dbname=contrib_regression --table=tbl_badindex -\! pg_repack --dbname=contrib_regression - --- --- after --- - -\d tbl_cluster -\d tbl_gistkey -\d tbl_only_ckey -\d tbl_only_pkey -\d tbl_with_dropped_column -\d tbl_with_dropped_toast -\d tbl_idxopts SELECT col1, to_char("time", 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster ORDER BY 1, 2; SELECT * FROM tbl_only_ckey ORDER BY 1; @@ -241,6 +87,19 @@ CREATE TABLE trg3 (id integer PRIMARY KEY); CREATE TRIGGER repack_trigger_1 BEFORE UPDATE ON trg3 FOR EACH ROW EXECUTE PROCEDURE trgtest(); \! pg_repack --dbname=contrib_regression --table=trg3 +-- +-- Table re-organization using specific column +-- + +-- reorganize table using cluster key. Sort in ascending order. +\! pg_repack --dbname=contrib_regression --table=tbl_order +SELECT ctid, c FROM tbl_order WHERE ctid <= '(0,10)'; + +-- reorganize table using specific column order. Sort in descending order. +\! pg_repack --dbname=contrib_regression --table=tbl_order -o "c DESC" +SELECT ctid, c FROM tbl_order WHERE ctid <= '(0,10)'; + + -- -- Dry run -- @@ -268,19 +127,6 @@ CREATE TABLE test_schema2.tbl2 (id INTEGER PRIMARY KEY); -- \! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-kill-backend --- --- no superuser check --- -DROP ROLE IF EXISTS nosuper; -CREATE ROLE nosuper WITH LOGIN; --- => OK -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --no-superuser-check --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --- => ERROR -\! pg_repack --dbname=contrib_regression --table=tbl_cluster --username=nosuper --no-superuser-check -DROP ROLE IF EXISTS nosuper; - -- -- exclude extension check -- diff --git a/regress/sql/repack-run.sql b/regress/sql/repack-run.sql new file mode 100644 index 0000000..0db7712 --- /dev/null +++ b/regress/sql/repack-run.sql @@ -0,0 +1,7 @@ +-- +-- do repack +-- + +\! pg_repack --dbname=contrib_regression --table=tbl_cluster +\! pg_repack --dbname=contrib_regression --table=tbl_badindex +\! pg_repack --dbname=contrib_regression diff --git a/regress/sql/repack-setup.sql b/regress/sql/repack-setup.sql new file mode 100644 index 0000000..abe00cf --- /dev/null +++ b/regress/sql/repack-setup.sql @@ -0,0 +1,143 @@ +SET client_min_messages = warning; + +-- +-- create table. +-- + +CREATE TABLE tbl_cluster ( + col1 int, + "time" timestamp, + ","")" text, + PRIMARY KEY (","")", col1) WITH (fillfactor = 75) +) WITH (fillfactor = 70); + +CREATE INDEX ","") cluster" ON tbl_cluster ("time", length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75); +ALTER TABLE tbl_cluster CLUSTER ON ","") cluster"; + +CREATE TABLE tbl_only_pkey ( + col1 int PRIMARY KEY, + ","")" text +); + +CREATE TABLE tbl_only_ckey ( + col1 int, + col2 timestamp, + ","")" text +) WITH (fillfactor = 70); + +CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")"); +ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey; + +CREATE TABLE tbl_gistkey ( + id integer PRIMARY KEY, + c circle +); + +CREATE INDEX cidx_circle ON tbl_gistkey USING gist (c); +ALTER TABLE tbl_gistkey CLUSTER ON cidx_circle; + +CREATE TABLE tbl_with_dropped_column ( + d1 text, + c1 text, + id integer PRIMARY KEY, + d2 text, + c2 text, + d3 text +); +ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75); +ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey; +CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75); +CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1); + +CREATE TABLE tbl_with_dropped_toast ( + i integer, + j integer, + t text, + PRIMARY KEY (i, j) +); +ALTER TABLE tbl_with_dropped_toast CLUSTER ON tbl_with_dropped_toast_pkey; + +CREATE TABLE tbl_badindex ( + id integer PRIMARY KEY, + n integer +); + +CREATE TABLE tbl_idxopts ( + i integer PRIMARY KEY, + t text +); +CREATE INDEX idxopts_t ON tbl_idxopts (t DESC NULLS LAST) WHERE (t != 'aaa'); + +-- Use this table to play with attribute options too +ALTER TABLE tbl_idxopts ALTER i SET STATISTICS 1; +ALTER TABLE tbl_idxopts ALTER t SET (n_distinct = -0.5); +CREATE TABLE tbl_with_toast ( + i integer PRIMARY KEY, + c text +); +ALTER TABLE tbl_with_toast SET (AUTOVACUUM_VACUUM_SCALE_FACTOR = 30, AUTOVACUUM_VACUUM_THRESHOLD = 300); +ALTER TABLE tbl_with_toast SET (TOAST.AUTOVACUUM_VACUUM_SCALE_FACTOR = 40, TOAST.AUTOVACUUM_VACUUM_THRESHOLD = 400); +CREATE TABLE tbl_with_mod_column_storage ( + id integer PRIMARY KEY, + c text +); +ALTER TABLE tbl_with_mod_column_storage ALTER c SET STORAGE MAIN; + +CREATE TABLE tbl_order (c int primary key); +-- +-- insert data +-- + +INSERT INTO tbl_cluster VALUES(1, '2008-12-31 10:00:00', 'admin'); +INSERT INTO tbl_cluster VALUES(2, '2008-01-01 00:00:00', 'king'); +INSERT INTO tbl_cluster VALUES(3, '2008-03-04 12:00:00', 'joker'); +INSERT INTO tbl_cluster VALUES(4, '2008-03-05 15:00:00', 'queen'); +INSERT INTO tbl_cluster VALUES(5, '2008-01-01 00:30:00', sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); + +INSERT INTO tbl_only_pkey VALUES(1, 'abc'); +INSERT INTO tbl_only_pkey VALUES(2, 'def'); + +INSERT INTO tbl_only_ckey VALUES(1, '2008-01-01 00:00:00', 'abc'); +INSERT INTO tbl_only_ckey VALUES(2, '2008-02-01 00:00:00', 'def'); + +INSERT INTO tbl_gistkey VALUES(1, '<(1,2),3>'); +INSERT INTO tbl_gistkey VALUES(2, '<(4,5),6>'); + +INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 2, 'd2', 'c2', 'd3'); +INSERT INTO tbl_with_dropped_column VALUES('d1', 'c1', 1, 'd2', 'c2', 'd3'); +ALTER TABLE tbl_with_dropped_column DROP COLUMN d1; +ALTER TABLE tbl_with_dropped_column DROP COLUMN d2; +ALTER TABLE tbl_with_dropped_column DROP COLUMN d3; +ALTER TABLE tbl_with_dropped_column ADD COLUMN c3 text; +CREATE VIEW view_for_dropped_column AS + SELECT * FROM tbl_with_dropped_column; + +INSERT INTO tbl_with_dropped_toast VALUES(1, 10, 'abc'); +INSERT INTO tbl_with_dropped_toast VALUES(2, 20, sqrt(2::numeric(1000,999))::text || sqrt(3::numeric(1000,999))::text); +ALTER TABLE tbl_with_dropped_toast DROP COLUMN t; + +INSERT INTO tbl_badindex VALUES(1, 10); +INSERT INTO tbl_badindex VALUES(2, 10); + +-- insert data that is always stored into the toast table if column type is extended. +SELECT setseed(0); INSERT INTO tbl_with_mod_column_storage SELECT 1, array_to_string(ARRAY(SELECT chr((random() * (127 - 32) + 32)::int) FROM generate_series(1, 3 * 1024) code), ''); + +-- This will fail. Silence the message as it's different across PG versions. +SET client_min_messages = fatal; +CREATE UNIQUE INDEX CONCURRENTLY idx_badindex_n ON tbl_badindex (n); +SET client_min_messages = warning; + +INSERT INTO tbl_idxopts VALUES (0, 'abc'), (1, 'aaa'), (2, NULL), (3, 'bbb'); + +-- Insert no-ordered data +INSERT INTO tbl_order SELECT generate_series(100, 51, -1); +CLUSTER tbl_order USING tbl_order_pkey; +INSERT INTO tbl_order SELECT generate_series(50, 1, -1); + +-- +-- before +-- + +SELECT * FROM tbl_with_dropped_column; +SELECT * FROM view_for_dropped_column; +SELECT * FROM tbl_with_dropped_toast; diff --git a/regress/travis_prepare.sh b/regress/travis_prepare.sh index 5644ed5..dbb1b40 100755 --- a/regress/travis_prepare.sh +++ b/regress/travis_prepare.sh @@ -30,6 +30,12 @@ else # See https://github.com/reorg/pg_repack/issues/63 sudo sed -i "s/main[[:space:]]*$/main ${PGVER}/" \ /etc/apt/sources.list.d/pgdg.list + + if [ "$PGTESTING" != "" ]; then + sudo sed -i "s/trusty-pgdg/trusty-pgdg-testing/" \ + /etc/apt/sources.list.d/pgdg.list + fi + sudo apt-get update sudo apt-get install -y "libpq5=${PGVER}*" "libpq-dev=${PGVER}*" sudo apt-mark hold libpq5 @@ -38,9 +44,24 @@ fi # Go somewhere else or sudo will fail cd / + # Already started because of installing posgresql-$PGVER # sudo -u postgres "$PGBIN/pg_ctl" -w -l /dev/null -D "$CONFDIR" start sudo -u postgres mkdir -p /var/lib/postgresql/testts sudo -u postgres "$PGBIN/psql" \ -c "create tablespace testts location '/var/lib/postgresql/testts'" + +# If the database was not provided by Travis it needs some customization +if [ "$PGTESTING" != "" ]; then + + # Allow local connections with no password + sudo sed -i \ + 's/\(^local[[:space:]]\+all[[:space:]]\+all[[:space:]]\+\).*/\1trust/' \ + "$CONFDIR/pg_hba.conf" + sudo -u postgres "$PGBIN/pg_ctl" -D "$DATADIR" reload + + sudo -u postgres "$PGBIN/psql" -c "create user travis superuser" +fi + +# Go back to the build dir cd -