Skip to content

Commit 174691b

Browse files
hlinnakareshke
authored andcommitted
Fix assertion if index is dropped during REFRESH CONCURRENTLY
When assertions are disabled, the built SQL statement is invalid and you get a "syntax error". So this isn't a serious problem, but let's avoid the assertion failure. Backpatch to all supported versions. Reviewed-by: Noah Misch
1 parent c2569aa commit 174691b

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

src/backend/commands/matview.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,9 +1347,12 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
13471347
*
13481348
* ExecRefreshMatView() checks that after taking the exclusive lock on the
13491349
* matview. So at least one unique index is guaranteed to exist here
1350-
* because the lock is still being held; so an Assert seems sufficient.
1350+
* because the lock is still being held. (One known exception is if a
1351+
* function called as part of refreshing the matview drops the index.
1352+
* That's a pretty silly thing to do.)
13511353
*/
1352-
Assert(foundUniqueIndex);
1354+
if (!foundUniqueIndex)
1355+
elog(ERROR, "could not find suitable unique index on materialized view");
13531356

13541357

13551358

src/test/regress/expected/matview.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,22 @@ REFRESH MATERIALIZED VIEW mvtest_mv_foo;
619619
REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
620620
DROP OWNED BY regress_user_mvtest CASCADE;
621621
DROP ROLE regress_user_mvtest;
622+
-- Concurrent refresh requires a unique index on the materialized
623+
-- view. Test what happens if it's dropped during the refresh.
624+
CREATE OR REPLACE FUNCTION mvtest_drop_the_index()
625+
RETURNS bool AS $$
626+
BEGIN
627+
EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx';
628+
RETURN true;
629+
END;
630+
$$ LANGUAGE plpgsql;
631+
CREATE MATERIALIZED VIEW drop_idx_matview AS
632+
SELECT 1 as i WHERE mvtest_drop_the_index();
633+
NOTICE: index "mvtest_drop_idx" does not exist, skipping
634+
CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i);
635+
REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview;
636+
ERROR: could not find suitable unique index on materialized view
637+
DROP MATERIALIZED VIEW drop_idx_matview; -- clean up
622638
-- make sure that create WITH NO DATA works via SPI
623639
BEGIN;
624640
CREATE FUNCTION mvtest_func()

src/test/regress/sql/matview.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,23 @@ REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
236236
DROP OWNED BY regress_user_mvtest CASCADE;
237237
DROP ROLE regress_user_mvtest;
238238

239+
-- Concurrent refresh requires a unique index on the materialized
240+
-- view. Test what happens if it's dropped during the refresh.
241+
CREATE OR REPLACE FUNCTION mvtest_drop_the_index()
242+
RETURNS bool AS $$
243+
BEGIN
244+
EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx';
245+
RETURN true;
246+
END;
247+
$$ LANGUAGE plpgsql;
248+
249+
CREATE MATERIALIZED VIEW drop_idx_matview AS
250+
SELECT 1 as i WHERE mvtest_drop_the_index();
251+
252+
CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i);
253+
REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview;
254+
DROP MATERIALIZED VIEW drop_idx_matview; -- clean up
255+
239256
-- make sure that create WITH NO DATA works via SPI
240257
BEGIN;
241258
CREATE FUNCTION mvtest_func()

0 commit comments

Comments
 (0)