aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-02-05 11:01:30 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-02-05 11:03:43 +0200
commita45c950ae35e53de4007c9dd0991d5005a4bee7b (patch)
treeb578e715712036aeb5ba4eecd4e9d6c60cfc4ac1
parentf4f2883521fc3f81765ab82eab2ffa31574f0a07 (diff)
downloadpostgresql-a45c950ae35e53de4007c9dd0991d5005a4bee7b.tar.gz
postgresql-a45c950ae35e53de4007c9dd0991d5005a4bee7b.zip
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
-rw-r--r--src/backend/commands/matview.c7
-rw-r--r--src/test/regress/expected/matview.out16
-rw-r--r--src/test/regress/sql/matview.sql17
3 files changed, 38 insertions, 2 deletions
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 0aa0a749dab..0ab8ba1a58d 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -803,9 +803,12 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
*
* ExecRefreshMatView() checks that after taking the exclusive lock on the
* matview. So at least one unique index is guaranteed to exist here
- * because the lock is still being held; so an Assert seems sufficient.
+ * because the lock is still being held. (One known exception is if a
+ * function called as part of refreshing the matview drops the index.
+ * That's a pretty silly thing to do.)
*/
- Assert(foundUniqueIndex);
+ if (!foundUniqueIndex)
+ elog(ERROR, "could not find suitable unique index on materialized view");
appendStringInfoString(&querybuf,
" AND newdata.* OPERATOR(pg_catalog.*=) mv.*) "
diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out
index c109d97635b..e811e1a049b 100644
--- a/src/test/regress/expected/matview.out
+++ b/src/test/regress/expected/matview.out
@@ -572,6 +572,22 @@ REFRESH MATERIALIZED VIEW mvtest_mv_foo;
REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
DROP OWNED BY regress_user_mvtest CASCADE;
DROP ROLE regress_user_mvtest;
+-- Concurrent refresh requires a unique index on the materialized
+-- view. Test what happens if it's dropped during the refresh.
+CREATE OR REPLACE FUNCTION mvtest_drop_the_index()
+ RETURNS bool AS $$
+BEGIN
+ EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx';
+ RETURN true;
+END;
+$$ LANGUAGE plpgsql;
+CREATE MATERIALIZED VIEW drop_idx_matview AS
+ SELECT 1 as i WHERE mvtest_drop_the_index();
+NOTICE: index "mvtest_drop_idx" does not exist, skipping
+CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i);
+REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview;
+ERROR: could not find suitable unique index on materialized view
+DROP MATERIALIZED VIEW drop_idx_matview; -- clean up
-- make sure that create WITH NO DATA works via SPI
BEGIN;
CREATE FUNCTION mvtest_func()
diff --git a/src/test/regress/sql/matview.sql b/src/test/regress/sql/matview.sql
index 68b9ccfd452..543e0a6d73a 100644
--- a/src/test/regress/sql/matview.sql
+++ b/src/test/regress/sql/matview.sql
@@ -231,6 +231,23 @@ REFRESH MATERIALIZED VIEW CONCURRENTLY mvtest_mv_foo;
DROP OWNED BY regress_user_mvtest CASCADE;
DROP ROLE regress_user_mvtest;
+-- Concurrent refresh requires a unique index on the materialized
+-- view. Test what happens if it's dropped during the refresh.
+CREATE OR REPLACE FUNCTION mvtest_drop_the_index()
+ RETURNS bool AS $$
+BEGIN
+ EXECUTE 'DROP INDEX IF EXISTS mvtest_drop_idx';
+ RETURN true;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE MATERIALIZED VIEW drop_idx_matview AS
+ SELECT 1 as i WHERE mvtest_drop_the_index();
+
+CREATE UNIQUE INDEX mvtest_drop_idx ON drop_idx_matview (i);
+REFRESH MATERIALIZED VIEW CONCURRENTLY drop_idx_matview;
+DROP MATERIALIZED VIEW drop_idx_matview; -- clean up
+
-- make sure that create WITH NO DATA works via SPI
BEGIN;
CREATE FUNCTION mvtest_func()