Fix busted Assert for CREATE MATVIEW ... WITH NO DATA.
authorTom Lane
Thu, 11 Aug 2016 15:22:25 +0000 (11:22 -0400)
committerTom Lane
Thu, 11 Aug 2016 15:22:25 +0000 (11:22 -0400)
Commit 874fe3aea changed the command tag returned for CREATE MATVIEW/CREATE
TABLE AS ... WITH NO DATA, but missed that there was code in spi.c that
expected the command tag to always be "SELECT".  Fortunately, the
consequence was only an Assert failure, so this oversight should have no
impact in production builds.

Since this code path was evidently un-exercised, add a regression test.

Per report from Shivam Saxena. Back-patch to 9.3, like the previous commit.

Michael Paquier

Report: <97218716-480B-4527-B5CD-D08D798A0C7B@dresources.com>

src/backend/executor/spi.c
src/test/regress/expected/matview.out
src/test/regress/sql/matview.sql

index 649040e8fd778b2dadf4736b39956895ad09077f..82d5005e872ad6666af166da033abd09f2d1ea06 100644 (file)
@@ -2186,15 +2186,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
                 */
                if (IsA(stmt, CreateTableAsStmt))
                {
-                   Assert(strncmp(completionTag, "SELECT ", 7) == 0);
-                   _SPI_current->processed = strtoul(completionTag + 7,
-                                                     NULL, 10);
+                   CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt;
+
+                   if (strncmp(completionTag, "SELECT ", 7) == 0)
+                       _SPI_current->processed =
+                           strtoul(completionTag + 7, NULL, 10);
+                   else
+                   {
+                       /* Must be a CREATE ... WITH NO DATA */
+                       Assert(ctastmt->into->skipData);
+                       _SPI_current->processed = 0;
+                   }
 
                    /*
                     * For historical reasons, if CREATE TABLE AS was spelled
                     * as SELECT INTO, return a special return code.
                     */
-                   if (((CreateTableAsStmt *) stmt)->is_select_into)
+                   if (ctastmt->is_select_into)
                        res = SPI_OK_SELINTO;
                }
                else if (IsA(stmt, CopyStmt))
index 716daa2b713f73dfde6520c24414cf1e1e7fb591..4aa91f416445defd09debe20557f0a530e8d0061 100644 (file)
@@ -553,3 +553,28 @@ REFRESH MATERIALIZED VIEW mv_foo;
 REFRESH MATERIALIZED VIEW CONCURRENTLY mv_foo;
 DROP OWNED BY user_dw CASCADE;
 DROP ROLE user_dw;
+-- make sure that create WITH NO DATA works via SPI
+BEGIN;
+CREATE FUNCTION mvtest_func()
+  RETURNS void AS $$
+BEGIN
+  CREATE MATERIALIZED VIEW mvtest1 AS SELECT 1 AS x;
+  CREATE MATERIALIZED VIEW mvtest2 AS SELECT 1 AS x WITH NO DATA;
+END;
+$$ LANGUAGE plpgsql;
+SELECT mvtest_func();
+ mvtest_func 
+-------------
+(1 row)
+
+SELECT * FROM mvtest1;
+ x 
+---
+ 1
+(1 row)
+
+SELECT * FROM mvtest2;
+ERROR:  materialized view "mvtest2" has not been populated
+HINT:  Use the REFRESH MATERIALIZED VIEW command.
+ROLLBACK;
index 7c2a93d556036936c038169caa76990e498b6ee5..20588d189f4782d6a1089e9961a7bc440c711824 100644 (file)
@@ -224,3 +224,17 @@ REFRESH MATERIALIZED VIEW mv_foo;
 REFRESH MATERIALIZED VIEW CONCURRENTLY mv_foo;
 DROP OWNED BY user_dw CASCADE;
 DROP ROLE user_dw;
+
+-- make sure that create WITH NO DATA works via SPI
+BEGIN;
+CREATE FUNCTION mvtest_func()
+  RETURNS void AS $$
+BEGIN
+  CREATE MATERIALIZED VIEW mvtest1 AS SELECT 1 AS x;
+  CREATE MATERIALIZED VIEW mvtest2 AS SELECT 1 AS x WITH NO DATA;
+END;
+$$ LANGUAGE plpgsql;
+SELECT mvtest_func();
+SELECT * FROM mvtest1;
+SELECT * FROM mvtest2;
+ROLLBACK;