From 0853630159944bb3652336602ff5f7f62cd27a5a Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 30 Mar 2015 16:01:44 -0300 Subject: [PATCH] Fix lost persistence setting during REINDEX INDEX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ReindexIndex() trusts a parser-built RangeVar with the persistence to use for the new copy of the index; but the parser naturally does not know what's the persistence of the original index. To find out the correct persistence, grab it from relcache. This bug was introduced by commit 85b506bbfc2937c9, and therefore no backpatch is necessary. Bug reported by Thom Brown, analysis and patch by Michael Paquier; test case provided by Fabrízio de Royes Mello. --- src/backend/commands/indexcmds.c | 18 ++++++++++++++++-- src/test/regress/expected/create_table.out | 22 ++++++++++++++++++++++ src/test/regress/sql/create_table.sql | 6 ++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 1c1d0da448..99acd4a6a2 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1685,14 +1685,28 @@ ReindexIndex(RangeVar *indexRelation) { Oid indOid; Oid heapOid = InvalidOid; + Relation irel; + char persistence; - /* lock level used here should match index lock reindex_index() */ + /* + * Find and lock index, and check permissions on table; use callback to + * obtain lock on table first, to avoid deadlock hazard. The lock level + * used here must match the index lock obtained in reindex_index(). + */ indOid = RangeVarGetRelidExtended(indexRelation, AccessExclusiveLock, false, false, RangeVarCallbackForReindexIndex, (void *) &heapOid); - reindex_index(indOid, false, indexRelation->relpersistence); + /* + * Obtain the current persistence of the existing index. We already hold + * lock on the index. + */ + irel = index_open(indOid, NoLock); + persistence = irel->rd_rel->relpersistence; + index_close(irel, NoLock); + + reindex_index(indOid, false, persistence); return indOid; } diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 34b5fc113d..8ba7bbc111 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -208,6 +208,28 @@ CREATE TABLE IF NOT EXISTS test_tsvector( ); NOTICE: relation "test_tsvector" already exists, skipping CREATE UNLOGGED TABLE unlogged1 (a int primary key); -- OK +CREATE TEMPORARY TABLE unlogged2 (a int primary key); -- OK +SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname; + relname | relkind | relpersistence +----------------+---------+---------------- + unlogged1 | r | u + unlogged1_pkey | i | u + unlogged2 | r | t + unlogged2_pkey | i | t +(4 rows) + +REINDEX INDEX unlogged1_pkey; +REINDEX INDEX unlogged2_pkey; +SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname; + relname | relkind | relpersistence +----------------+---------+---------------- + unlogged1 | r | u + unlogged1_pkey | i | u + unlogged2 | r | t + unlogged2_pkey | i | t +(4 rows) + +DROP TABLE unlogged2; INSERT INTO unlogged1 VALUES (42); CREATE UNLOGGED TABLE public.unlogged2 (a int primary key); -- also OK CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key); -- not OK diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 08029a99b0..03bb5ff704 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -246,6 +246,12 @@ CREATE TABLE IF NOT EXISTS test_tsvector( ); CREATE UNLOGGED TABLE unlogged1 (a int primary key); -- OK +CREATE TEMPORARY TABLE unlogged2 (a int primary key); -- OK +SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname; +REINDEX INDEX unlogged1_pkey; +REINDEX INDEX unlogged2_pkey; +SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname; +DROP TABLE unlogged2; INSERT INTO unlogged1 VALUES (42); CREATE UNLOGGED TABLE public.unlogged2 (a int primary key); -- also OK CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key); -- not OK