Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b96115a

Browse files
committed
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 5a9167c commit b96115a

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

src/backend/commands/matview.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -801,9 +801,12 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
801801
*
802802
* ExecRefreshMatView() checks that after taking the exclusive lock on the
803803
* matview. So at least one unique index is guaranteed to exist here
804-
* because the lock is still being held; so an Assert seems sufficient.
804+
* because the lock is still being held. (One known exception is if a
805+
* function called as part of refreshing the matview drops the index.
806+
* That's a pretty silly thing to do.)
805807
*/
806-
Assert(foundUniqueIndex);
808+
if (!foundUniqueIndex)
809+
elog(ERROR, "could not find suitable unique index on materialized view");
807810

808811
appendStringInfoString(&querybuf,
809812
" AND newdata.* OPERATOR(pg_catalog.*=) mv.*) "

src/test/regress/expected/matview.out

+16
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,22 @@ REFRESH MATERIALIZED VIEW mvtest_mv_foo;
572572
REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
573573
DROP OWNED BY regress_user_mvtest CASCADE;
574574
DROP ROLE regress_user_mvtest;
575+
-- Concurrent refresh requires a unique index on the materialized
576+
-- view. Test what happens if it's dropped during the refresh.
577+
CREATE OR REPLACE FUNCTION mvtest_drop_the_index()
578+
RETURNS bool AS $$
579+
BEGIN
580+
EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx';
581+
RETURN true;
582+
END;
583+
$$ LANGUAGE plpgsql;
584+
CREATE MATERIALIZED VIEW drop_idx_matview AS
585+
SELECT 1 as i WHERE mvtest_drop_the_index();
586+
NOTICE: index "mvtest_drop_idx" does not exist, skipping
587+
CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i);
588+
REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview;
589+
ERROR: could not find suitable unique index on materialized view
590+
DROP MATERIALIZED VIEW drop_idx_matview; -- clean up
575591
-- make sure that create WITH NO DATA works via SPI
576592
BEGIN;
577593
CREATE FUNCTION mvtest_func()

src/test/regress/sql/matview.sql

+17
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,23 @@ REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
231231
DROP OWNED BY regress_user_mvtest CASCADE;
232232
DROP ROLE regress_user_mvtest;
233233

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

0 commit comments

Comments
 (0)